最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中后臺(tái)線程實(shí)例解析

 更新時(shí)間:2018年02月05日 08:40:23   作者:szu_lg  
這篇文章主要介紹了Java中后臺(tái)線程實(shí)例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下

本文研究的主要是Java中后臺(tái)線程的相關(guān)問題,具體介紹如下。

以前從來沒有聽說過,java中有后臺(tái)線程這種東西。一般來說,JVM(JAVA虛擬機(jī))中一般會(huì)包括倆種線程,分別是用戶線程和后臺(tái)線程。所謂后臺(tái)線程(daemon)線程指的是:在程序運(yùn)行的時(shí)候在后臺(tái)提供的一種通用的服務(wù)的線程,并且這種線程并不屬于程序中不可或缺的部分。因此,當(dāng)所有的非后臺(tái)線程結(jié)束的時(shí)候,也就是用戶線程都結(jié)束的時(shí)候,程序也就終止了。同時(shí),會(huì)殺死進(jìn)程中的所有的后臺(tái)線程。反過來說,只要有任何非后臺(tái)線程還在運(yùn)行,程序就不會(huì)結(jié)束。不如執(zhí)行main()的就是一個(gè)非后臺(tái)線程。

基于這個(gè)特點(diǎn),當(dāng)虛擬機(jī)中的用戶線程全部退出運(yùn)行時(shí),守護(hù)線程沒有服務(wù)的對(duì)象后,JVM也就退出了。

這點(diǎn)JDK源碼中的介紹已經(jīng)說明這一點(diǎn)了。

* Marks this thread as either a {@linkplain #isDaemon daemon} thread
* or a user thread. The Java Virtual Machine exits when the only
* threads running are all daemon threads.

1.后臺(tái)線程的啟動(dòng)的條件:

/*必須在啟動(dòng)線程之前調(diào)用SetDaemon()方法,才能把這個(gè)線程設(shè)置為后臺(tái)線程。
* 在這個(gè)程序里面,當(dāng)我們輸入了字符串以后,那么Main線程就會(huì)停止運(yùn)行了
* 那么程序中已經(jīng)沒有可以運(yùn)行的用戶的線程了。所以后臺(tái)線程就會(huì)被停止了
* JVM也就會(huì)被停停止了,感興趣的讀者可以自己嘗試一下*/
public class DaemonRunner implements Runnable {
	@Override
	 public void run() {
		while (true) {
			for (int i = 0; i < 3; i++) {
				System.out.println("守護(hù)線程" + i);
			}
		}
	}
	public static void main(String[] args) {
		Thread daemon = new Thread(new DaemonRunner());
		daemon.setDaemon(true);
		daemon.start();
		Scanner s = new Scanner(System.in);
		String string=s.nextLine();
		Runtime.getRuntime().addShutdownHook(new Thread(){
			@Override
			   public void run() {
				super.run();
				System.out.println("JVM退出");
				try {
					TimeUnit.MILLISECONDS.sleep(50);
				}
				catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		);
	}
}

2.在后臺(tái)線程中啟動(dòng)的線程都屬于后臺(tái)線程。盡管你沒有明確指明它們是后臺(tái)線程,但是它們的確是后臺(tái)線程。

/*可以通過調(diào)用isDaemon()方法來確定線程是否是一個(gè)后臺(tái)線程。如果是一個(gè)后臺(tái)線程,
* 那么它創(chuàng)建的任何線程都被自動(dòng)設(shè)置成后臺(tái)的線程
* 在這個(gè)實(shí)例中,Daemon線程被設(shè)置成了后臺(tái)模式,然后派生出許多子線程,這些線程并沒有被設(shè)置成
* 后臺(tái)模式,不過它們的確是后臺(tái)線程。接著,Daemon線程進(jìn)入了無限循環(huán),并且在循環(huán)里調(diào)用了yield方法
* 把控制權(quán)交給其它的線程或者進(jìn)程*/
class Daemon implements Runnable{
	private Thread[] t = new Thread[10];
	@Override
	 public void run() {
		for (int i = 0; i < t.length; i++) {
			t[i] = new Thread(new DaemonSpawn());
			t[i].start();
			System.out.println("DaemonSpawn " + i + "started");
		}
		for (int i = 0; i < t.length; i++) {
			System.out.println("t[" + i + "].isDaemon" + t[i].isDaemon());
		}
		while (true) {
			Thread.yield();
		}
	}
}
class DaemonSpawn implements Runnable{
	@Override
	 public void run() {
		while (true) {
			Thread.yield();
		}
	}
}
public class Daemons {
	public static void main(String[] args) {
		Thread d = new Thread(new Daemon());
		d.setDaemon(true);
		d.start();
		System.out.println("d.isDaemon()=" + d.isDaemon());
		try {
			TimeUnit.SECONDS.sleep(1);
			//讓啟動(dòng)的后臺(tái)的線程可以獲得一定的執(zhí)行的時(shí)間。
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

最后的執(zhí)行的結(jié)果如下:

d.isDaemon()=true
DaemonSpawn 0started
DaemonSpawn 1started
DaemonSpawn 2started
DaemonSpawn 3started
DaemonSpawn 4started
DaemonSpawn 5started
DaemonSpawn 6started
DaemonSpawn 7started
DaemonSpawn 8started
DaemonSpawn 9started
t[0].isDaemontrue
t[1].isDaemontrue
t[2].isDaemontrue
t[3].isDaemontrue
t[4].isDaemontrue
t[5].isDaemontrue
t[6].isDaemontrue
t[7].isDaemontrue
t[8].isDaemontrue
t[9].isDaemontrue

3.通過為Executors.newCachedThreadPool()方法指定一個(gè)ThreadFactory的對(duì)象。通過這種方法,我們也可以將
我們想要啟動(dòng)的線程設(shè)置為后臺(tái)線程。

/*在這個(gè)例子中,對(duì)于這個(gè)靜態(tài)的構(gòu)造方法:Executors.newCachedThreadPool(new DaemonThreadFactory()
* 我們可以為傳入一個(gè)ThreadFactory的對(duì)象,那么我們就可以通過這種方法,將我們想要啟動(dòng)的線程設(shè)置為后臺(tái)線程
* 這是要注意的。*/
class DaemonThreadFactory implements ThreadFactory{
	@Override
	  public Thread newThread(Runnable r) {
		Thread t = new Thread(r);
		t.setDaemon(true);
		return t;
	}
}
/*在這個(gè)例子中,在Main方法中,會(huì)首先調(diào)用Main方法中的普通的方法,“ System.out.println("All dameons started");”
* 所以會(huì)首先打印這一條語句。然后在主線程休眠期間,相應(yīng)的后臺(tái)線程,就會(huì)獲得執(zhí)行的時(shí)間,最后在Main線程
* 結(jié)束了運(yùn)行的時(shí)候,也就是當(dāng)Main線程從休眠中恢復(fù)過來的時(shí)候,那么Main線性就會(huì)結(jié)束運(yùn)行。接著,
* 那么所有的后臺(tái)的線程都會(huì)停止。JVM也會(huì)停止執(zhí)行。*/
public class DaemonFromFactory implements Runnable {
	@Override
	  public void run() {
		try {
			while (true) {
				TimeUnit.MILLISECONDS.sleep(100);
				System.out.println(Thread.currentThread() + " " + this);
			}
		}
		catch (InterruptedException e) {
			System.out.println("Interrupted");
		}
	}
	public static void main(String[] args) {
		ExecutorService exec = Executors.newCachedThreadPool(new DaemonThreadFactory());
		for (int i = 0; i < 10; i++) {
			exec.execute(new DaemonFromFactory());
		}
		System.out.println("All dameons started");
		try {
			TimeUnit.MILLISECONDS.sleep(500);
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

最后的輸出的結(jié)果為:

All dameons started
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-0,5,main] Concurrency.DaemonFromFactory@144fe080
Thread[Thread-1,5,main] Concurrency.DaemonFromFactory@104fa29e
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f
Thread[Thread-9,5,main] Concurrency.DaemonFromFactory@1a7288d1
Thread[Thread-7,5,main] Concurrency.DaemonFromFactory@25144c3e
Thread[Thread-4,5,main] Concurrency.DaemonFromFactory@288523d
Thread[Thread-6,5,main] Concurrency.DaemonFromFactory@1edae2a8
Thread[Thread-5,5,main] Concurrency.DaemonFromFactory@626007aa
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-6,5,main] Concurrency.DaemonFromFactory@1edae2a8
Thread[Thread-5,5,main] Concurrency.DaemonFromFactory@626007aa
Thread[Thread-4,5,main] Concurrency.DaemonFromFactory@288523d
Thread[Thread-9,5,main] Concurrency.DaemonFromFactory@1a7288d1
Thread[Thread-7,5,main] Concurrency.DaemonFromFactory@25144c3e
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f
Thread[Thread-1,5,main] Concurrency.DaemonFromFactory@104fa29e
Thread[Thread-0,5,main] Concurrency.DaemonFromFactory@144fe080
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-6,5,main] Concurrency.DaemonFromFactory@1edae2a8
Thread[Thread-1,5,main] Concurrency.DaemonFromFactory@104fa29e
Thread[Thread-0,5,main] Concurrency.DaemonFromFactory@144fe080
Thread[Thread-7,5,main] Concurrency.DaemonFromFactory@25144c3e
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f
Thread[Thread-5,5,main] Concurrency.DaemonFromFactory@626007aa
Thread[Thread-9,5,main] Concurrency.DaemonFromFactory@1a7288d1
Thread[Thread-4,5,main] Concurrency.DaemonFromFactory@288523d
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f
Thread[Thread-7,5,main] Concurrency.DaemonFromFactory@25144c3e
Thread[Thread-4,5,main] Concurrency.DaemonFromFactory@288523d
Thread[Thread-6,5,main] Concurrency.DaemonFromFactory@1edae2a8
Thread[Thread-1,5,main] Concurrency.DaemonFromFactory@104fa29e
Thread[Thread-0,5,main] Concurrency.DaemonFromFactory@144fe080
Thread[Thread-9,5,main] Concurrency.DaemonFromFactory@1a7288d1
Thread[Thread-5,5,main] Concurrency.DaemonFromFactory@626007aa
Thread[Thread-3,5,main] Concurrency.DaemonFromFactory@56214c1
Thread[Thread-2,5,main] Concurrency.DaemonFromFactory@5724147d
Thread[Thread-8,5,main] Concurrency.DaemonFromFactory@5b069a7f

4.首先應(yīng)該意識(shí)到如果在用戶線程突然退出的時(shí)候,那么后臺(tái)線程在不執(zhí)行finally子句的情況下就會(huì)終止其run方法。

/*當(dāng)你調(diào)用這個(gè)程序的時(shí)候,你將看到finally子句不會(huì)執(zhí)行,但是如果你注釋掉對(duì)setDaemon()的調(diào)用,你將看到
* finally 子句將會(huì)執(zhí)行.
* 這種行為是正確的。即便你基于前面對(duì)finally給出的承諾,并不希望出現(xiàn)這種行為。但是情況就是這樣
* 當(dāng)最后一個(gè)非后臺(tái)的線程終止的時(shí)候,后臺(tái)線程就會(huì)突然的停止。因?yàn)橐坏﹎ain()退出后,JVM就會(huì)立即關(guān)閉所有后臺(tái)的
* 線程。因?yàn)槟悴荒芤詢?yōu)雅的方式來關(guān)閉后臺(tái)線程,所以它們幾乎不是一種好的思想。非后臺(tái)的Executor通常是一種
* 更好的方式,因?yàn)镋xecutor控制的所有的任務(wù)可以同時(shí)被關(guān)閉。*/
class ADaemon implements Runnable{
  @Override
  public void run() {
    System.out.println("Starting ADaemon");
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      System.out.println("Exiting via InterruptedException");
    }finally {
      System.out.println("This should always run?");
    }
  }
}
public class DaemonsDontRunFinally {
  public static void main(String[] args) {
    Thread t = new Thread(new ADaemon());
    t.setDaemon(true);
    t.start();
  }
}

最后的輸出的結(jié)果如下:

Starting ADaemon

但是如果情況變?yōu)槿缦碌那闆r,輸出的結(jié)果又會(huì)不一樣了:

class ADaemon implements Runnable{
  @Override
  public void run() {
    System.out.println("Starting ADaemon");
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      System.out.println("Exiting via InterruptedException");
    }finally {
      System.out.println("This should always run?");
    }
  }
}
public class DaemonsDontRunFinally {
  public static void main(String[] args) {
    Thread t = new Thread(new ADaemon());
    t.setDaemon(true);
    t.start();
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

由于主線程不是突然退出的,主線程在休眠期間,后臺(tái)線程得到了執(zhí)行的時(shí)間,所以最后的打印的結(jié)果為:

Starting ADaemon
This should always run?

總結(jié)

以上就是本文關(guān)于Java中后臺(tái)線程實(shí)例解析的全部內(nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!

相關(guān)文章

  • 關(guān)于jdk8升級(jí)jdk21 cxf報(bào)錯(cuò)的踩坑記錄

    關(guān)于jdk8升級(jí)jdk21 cxf報(bào)錯(cuò)的踩坑記錄

    在升級(jí)Java項(xiàng)目時(shí),從JDK1.8和Spring2遷移到JDK21和Spring3后,遇到了JAXBException錯(cuò)誤,原因是從JDK11開始移除了jaxb模塊,而cxf在編譯動(dòng)態(tài)客戶端時(shí)默認(rèn)classpath不包含必要的類,解決方法是在jar包同級(jí)目錄創(chuàng)建libs并添加jakarta.xml.bind-api
    2024-10-10
  • SpringBoot統(tǒng)一處理功能實(shí)現(xiàn)的全過程

    SpringBoot統(tǒng)一處理功能實(shí)現(xiàn)的全過程

    最近在做項(xiàng)目時(shí)需要對(duì)異常進(jìn)行全局統(tǒng)一處理,主要是一些分類入庫以及記錄日志等,下面這篇文章主要給大家介紹了關(guān)于SpringBoot統(tǒng)一功能處理實(shí)現(xiàn)的相關(guān)資料,文中通過圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-03-03
  • Spring Boot詳解配置文件的用途與用法

    Spring Boot詳解配置文件的用途與用法

    SpringBoot項(xiàng)目是一個(gè)標(biāo)準(zhǔn)的Maven項(xiàng)目,它的配置文件需要放在src/main/resources/下,其文件名必須為application,其存在兩種文件形式,分別是properties和yaml(或者yml)文件
    2022-06-06
  • SpringBoot參數(shù)校驗(yàn)之@Valid與@Validated的用法與場景

    SpringBoot參數(shù)校驗(yàn)之@Valid與@Validated的用法與場景

    這篇文章主要介紹了SpringBoot參數(shù)校驗(yàn)的用法與場景,在實(shí)際開發(fā)中,參數(shù)校驗(yàn)是保證接口安全性和數(shù)據(jù)完整性的重要手段,Spring Boot提供了@Valid和@Validated兩個(gè)核心注解來實(shí)現(xiàn)參數(shù)校驗(yàn),但許多開發(fā)者對(duì)它們的區(qū)別和使用場景存在疑惑,需要的朋友可以參考下
    2025-02-02
  • SpringBoot如何使用過濾器進(jìn)行XSS防御

    SpringBoot如何使用過濾器進(jìn)行XSS防御

    想對(duì)全局的請(qǐng)求都進(jìn)行XSS防御可以使用servlet中的過濾器或者spring mvc中的攔截器,下面我們就來看看如何使用servlet中的過濾器進(jìn)行XSS防御吧
    2024-11-11
  • Java web.xml之contextConfigLocation作用案例詳解

    Java web.xml之contextConfigLocation作用案例詳解

    這篇文章主要介紹了Java web.xml之contextConfigLocation作用案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java數(shù)據(jù)類型Integer與int的區(qū)別詳細(xì)解析

    Java數(shù)據(jù)類型Integer與int的區(qū)別詳細(xì)解析

    這篇文章主要介紹了Java數(shù)據(jù)類型Integer與int的區(qū)別詳細(xì)解析,Ingeter是int的包裝類,int的初值為0,Ingeter的初值為null,int和integer(無論new否)比,都為true,因?yàn)闀?huì)把Integer自動(dòng)拆箱為int再去比,需要的朋友可以參考下
    2023-12-12
  • Spring運(yùn)行時(shí)手動(dòng)注入bean的方法實(shí)例

    Spring運(yùn)行時(shí)手動(dòng)注入bean的方法實(shí)例

    spring給我們提供了IOC服務(wù),讓我們可以用注解的方式,方便的使用bean的相互引用,下面這篇文章主要給大家介紹了關(guān)于Spring運(yùn)行時(shí)手動(dòng)注入bean的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • Java實(shí)現(xiàn)漢字轉(zhuǎn)全拼音的方法總結(jié)

    Java實(shí)現(xiàn)漢字轉(zhuǎn)全拼音的方法總結(jié)

    在軟件開發(fā)中,經(jīng)常會(huì)遇到需要將漢字轉(zhuǎn)換成拼音的場景,比如在搜索引擎優(yōu)化、數(shù)據(jù)存儲(chǔ)、國際化等方面,Java作為一種廣泛使用的編程語言,提供了多種方法來實(shí)現(xiàn)漢字到拼音的轉(zhuǎn)換,本文將詳細(xì)介紹幾種常用的Java漢字轉(zhuǎn)全拼音的方法,并提供具體的代碼示例和步驟
    2024-12-12
  • 關(guān)于jackson序列化和feign返回值的問題

    關(guān)于jackson序列化和feign返回值的問題

    這篇文章主要介紹了關(guān)于jackson序列化和feign返回值的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評(píng)論

衡阳市| 隆回县| 沂水县| 天柱县| 丹凤县| 柘城县| 雅江县| 乌什县| 江阴市| 富源县| 扶风县| 凤翔县| 淅川县| 五大连池市| 汉源县| 潼关县| 镇平县| 静乐县| 句容市| 岳普湖县| 榆社县| 崇信县| 灵石县| 冀州市| 九龙县| 黑河市| 定州市| 九寨沟县| 永泰县| 兰州市| 临汾市| 黄平县| 黑河市| 边坝县| 华池县| 翁牛特旗| 普宁市| 伊通| 舟山市| 宿松县| 桦南县|