日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Java中用戶(hù)線程和守護(hù)線程區(qū)別這么大?

本文轉(zhuǎn)載自微信公眾號(hào)「Java中文社群」,作者磊哥。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java中文社群公眾號(hào)。

創(chuàng)新互聯(lián)建站服務(wù)項(xiàng)目包括溫縣網(wǎng)站建設(shè)、溫縣網(wǎng)站制作、溫縣網(wǎng)頁(yè)制作以及溫縣網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專(zhuān)注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,溫縣網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶(hù)以成都為中心已經(jīng)輻射到溫縣省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶(hù)的支持與信任!

在 Java 語(yǔ)言中線程分為兩類(lèi):用戶(hù)線程和守護(hù)線程,而二者之間的區(qū)別卻鮮有人知,所以本文磊哥帶你來(lái)看二者之間的區(qū)別,以及守護(hù)線程需要注意的一些事項(xiàng)。

1.默認(rèn)用戶(hù)線程

Java 語(yǔ)言中無(wú)論是線程還是線程池,默認(rèn)都是用戶(hù)線程,因此用戶(hù)線程也被成為普通線程。

以線程為例,想要查看線程是否為守護(hù)線程只需通過(guò)調(diào)用 isDaemon() 方法查詢(xún)即可,如果查詢(xún)的值為 false 則表示不為守護(hù)線程,自然也就屬于用戶(hù)線程了,如下代碼所示:

  
 
 
 
  1. public static void main(String[] args) throws InterruptedException {
  2.     Thread thread = new Thread(new Runnable() {
  3.         @Override
  4.         public void run() {
  5.             System.out.println("我是子線程");
  6.         }
  7.     });
  8.     System.out.println("子線程==守護(hù)線程:" + thread.isDaemon());
  9.     System.out.println("主線程==守護(hù)線程:" + Thread.currentThread().isDaemon());
  10. }

以上程序的執(zhí)行結(jié)果為:

從上述結(jié)果可以看出,默認(rèn)情況下主線程和創(chuàng)建的新線程都為用戶(hù)線程。

PS:Thread.currentThread() 的意思是獲取執(zhí)行當(dāng)前代碼的線程實(shí)例。

2.主動(dòng)修改為守護(hù)線程

守護(hù)線程(Daemon Thread)也被稱(chēng)之為后臺(tái)線程或服務(wù)線程,守護(hù)線程是為用戶(hù)線程服務(wù)的,當(dāng)程序中的用戶(hù)線程全部執(zhí)行結(jié)束之后,守護(hù)線程也會(huì)跟隨結(jié)束。

守護(hù)線程的角色就像“服務(wù)員”,而用戶(hù)線程的角色就像“顧客”,當(dāng)“顧客”全部走了之后(全部執(zhí)行結(jié)束),那“服務(wù)員”(守護(hù)線程)也就沒(méi)有了存在的意義,所以當(dāng)一個(gè)程序中的全部用戶(hù)線程都結(jié)束執(zhí)行之后,那么無(wú)論守護(hù)線程是否還在工作都會(huì)隨著用戶(hù)線程一塊結(jié)束,整個(gè)程序也會(huì)隨之結(jié)束運(yùn)行。

那如何將默認(rèn)的用戶(hù)線程修改為守護(hù)線程呢?

這個(gè)問(wèn)題要分為兩種情況來(lái)回答,首先如果是線程,則可以通過(guò)設(shè)置 setDaemon(true) 方法將用戶(hù)線程直接修改為守護(hù)線程,而如果是線程池則需要通過(guò) ThreadFactory 將線程池中的每個(gè)線程都為守護(hù)線程才行,接下來(lái)我們分別來(lái)實(shí)現(xiàn)一下。

2.1 設(shè)置線程為守護(hù)線程

如果使用的是線程,可以通過(guò) setDaemon(true) 方法將線程類(lèi)型更改為守護(hù)線程,如下代碼所示:

  
 
 
 
  1. public static void main(String[] args) throws InterruptedException {
  2.     Thread thread = new Thread(new Runnable() {
  3.         @Override
  4.         public void run() {
  5.             System.out.println("我是子線程");
  6.         }
  7.     });
  8.     // 設(shè)置子線程為守護(hù)線程
  9.     thread.setDaemon(true);
  10.     System.out.println("子線程==守護(hù)線程:" + thread.isDaemon());
  11.     System.out.println("主線程==守護(hù)線程:" + Thread.currentThread().isDaemon());
  12. }

以上程序的執(zhí)行結(jié)果為:

2.2 設(shè)置線程池為守護(hù)線程

要把線程池設(shè)置為守護(hù)線程相對(duì)來(lái)說(shuō)麻煩一些,需要將線程池中的所有線程都設(shè)置成守護(hù)線程,這個(gè)時(shí)候就需要使用 ThreadFactory 來(lái)定義線程池中每個(gè)線程的線程類(lèi)型了,具體實(shí)現(xiàn)代碼如下:

  
 
 
 
  1. // 創(chuàng)建固定個(gè)數(shù)的線程池
  2. ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
  3.     @Override
  4.     public Thread newThread(Runnable r) {
  5.         Thread t = new Thread(r);
  6.         // 設(shè)置線程為守護(hù)線程
  7.         t.setDaemon(false);
  8.         return t;
  9.     }
  10. });

如下圖所示:

如上圖所示,可以看出,整個(gè)程序中有 10 個(gè)守護(hù)線程都是我創(chuàng)建的。其他幾種創(chuàng)建線程池的設(shè)置方式類(lèi)似,都是通過(guò) ThreadFactory 統(tǒng)一設(shè)置的,這里就不一一列舉了。

3.守護(hù)線程 VS 用戶(hù)線程

通過(guò)前面的學(xué)習(xí)我們可以創(chuàng)建兩種不同的線程類(lèi)型了,那二者有什么差異呢?接下來(lái)我們使用一個(gè)小示例來(lái)看一下。

下面我們創(chuàng)建一個(gè)線程,分別將這個(gè)線程設(shè)置為用戶(hù)線程和守護(hù)線程,在每個(gè)線程中執(zhí)行一個(gè) for 循環(huán),總共執(zhí)行 10 次信息打印,每次打印之后休眠 100 毫秒,來(lái)觀察程序的運(yùn)行結(jié)果。

3.1 用戶(hù)線程

新建的線程默認(rèn)就是用戶(hù)線程,因此我們無(wú)需對(duì)線程進(jìn)行任何特殊的處理,執(zhí)行 for 循環(huán)即可(總共執(zhí)行 10 次信息打印,每次打印之后休眠 100 毫秒),實(shí)現(xiàn)代碼如下:

  
 
 
 
  1. /**
  2.  * Author:Java中文社群
  3.  */
  4. public class DaemonExample {
  5.     public static void main(String[] args) throws InterruptedException {
  6.         Thread thread = new Thread(new Runnable() {
  7.             @Override
  8.             public void run() {
  9.                 for (int i = 1; i <= 10; i++) {
  10.                     // 打印 i 信息
  11.                     System.out.println("i:" + i);
  12.                     try {
  13.                         // 休眠 100 毫秒
  14.                         Thread.sleep(100);
  15.                     } catch (InterruptedException e) {
  16.                         e.printStackTrace();
  17.                     }
  18.                 }
  19.             }
  20.         });
  21.         // 啟動(dòng)線程
  22.         thread.start();
  23.     }
  24. }

以上程序執(zhí)行結(jié)果如下:

從上述結(jié)果可以看出,當(dāng)程序執(zhí)行完 10 次打印之后才會(huì)正常結(jié)束進(jìn)程。

3.2 守護(hù)線程

  
 
 
 
  1. /**
  2.  * Author:Java中文社群
  3.  */
  4. public class DaemonExample {
  5.     public static void main(String[] args) throws InterruptedException {
  6.         Thread thread = new Thread(new Runnable() {
  7.             @Override
  8.             public void run() {
  9.                 for (int i = 1; i <= 10; i++) {
  10.                     // 打印 i 信息
  11.                     System.out.println("i:" + i);
  12.                     try {
  13.                         // 休眠 100 毫秒
  14.                         Thread.sleep(100);
  15.                     } catch (InterruptedException e) {
  16.                         e.printStackTrace();
  17.                     }
  18.                 }
  19.             }
  20.         });
  21.         // 設(shè)置為守護(hù)線程
  22.         thread.setDaemon(true);
  23.         // 啟動(dòng)線程
  24.         thread.start();
  25.     }
  26. }

以上程序執(zhí)行結(jié)果如下:

從上述結(jié)果可以看出,當(dāng)線程設(shè)置為守護(hù)線程之后,整個(gè)程序不會(huì)等守護(hù)線程 for 循環(huán) 10 次之后再進(jìn)行關(guān)閉,而是當(dāng)主線程結(jié)束之后,守護(hù)線程只執(zhí)行了一次循環(huán)就結(jié)束運(yùn)行了,由此可以看出守護(hù)線程和用戶(hù)線程的不同。

3.3 小結(jié)

守護(hù)線程是為用戶(hù)線程服務(wù)的,當(dāng)一個(gè)程序中的所有用戶(hù)線程都執(zhí)行完成之后程序就會(huì)結(jié)束運(yùn)行,程序結(jié)束運(yùn)行時(shí)不會(huì)管守護(hù)線程是否正在運(yùn)行,由此我們可以看出守護(hù)線程在 Java 體系中權(quán)重是比較低的。

4.守護(hù)線程注意事項(xiàng)

守護(hù)線程的使用需要注意以下三個(gè)問(wèn)題:

  1. 守護(hù)線程的設(shè)置 setDaemon(true) 必須要放在線程的 start() 之前,否則程序會(huì)報(bào)錯(cuò)。
  2. 在守護(hù)線程中創(chuàng)建的所有子線程都是守護(hù)線程。
  3. 使用 jojn() 方法會(huì)等待一個(gè)線程執(zhí)行完,無(wú)論此線程是用戶(hù)線程還是守護(hù)線程。

接下來(lái)我們分別演示一下,以上的注意事項(xiàng)。

4.1 setDaemon 執(zhí)行順序

當(dāng)我們將 setDaemon(true) 設(shè)置在 start() 之后,如下代碼所示:

  
 
 
 
  1. public static void main(String[] args) throws InterruptedException {
  2.     Thread thread = new Thread(new Runnable() {
  3.         @Override
  4.         public void run() {
  5.             for (int i = 1; i <= 10; i++) {
  6.                 // 打印 i 信息
  7.                 System.out.println("i:" + i + ",isDaemon:" +
  8.                             Thread.currentThread().isDaemon());
  9.                 try {
  10.                     // 休眠 100 毫秒
  11.                     Thread.sleep(100);
  12.                 } catch (InterruptedException e) {
  13.                     e.printStackTrace();
  14.                 }
  15.             }
  16.         }
  17.     });
  18.     // 啟動(dòng)線程
  19.     thread.start();
  20.     // 設(shè)置為守護(hù)線程
  21.     thread.setDaemon(true);
  22. }

以上程序執(zhí)行結(jié)果如下:

從上述結(jié)果可以看出,當(dāng)我們將 setDaemon(true) 設(shè)置在 start() 之后,不但程序的執(zhí)行會(huì)報(bào)錯(cuò),而且設(shè)置的守護(hù)線程也不會(huì)生效。

4.2 守護(hù)線程的子線程

  
 
 
 
  1. public static void main(String[] args) throws InterruptedException {
  2.     Thread thread = new Thread(new Runnable() {
  3.         @Override
  4.         public void run() {
  5.             Thread thread2 = new Thread(new Runnable() {
  6.                 @Override
  7.                 public void run() {
  8.                 }
  9.             });
  10.             System.out.println("守護(hù)線程的子線程 thread2 isDaemon:" +
  11.                                thread2.isDaemon());
  12.         }
  13.     });
  14.     // 設(shè)置為守護(hù)線程
  15.     thread.setDaemon(true);
  16.     // 啟動(dòng)線程
  17.     thread.start();
  18.     Thread.sleep(1000);
  19. }

以上程序執(zhí)行結(jié)果如下:

從上述結(jié)果可以看出,守護(hù)線程中創(chuàng)建的子線程,默認(rèn)情況下也屬于守護(hù)線程。

4.3 join 與守護(hù)線程

通過(guò) 3.2 部分的內(nèi)容我們可以看出,默認(rèn)情況下程序結(jié)束并不會(huì)等待守護(hù)線程執(zhí)行完,而當(dāng)我們調(diào)用線程的等待方法 join() 時(shí),執(zhí)行的結(jié)果就會(huì)和 3.2 的結(jié)果有所不同,下面我們一起來(lái)看吧,示例代碼如下:

  
 
 
 
  1. public static void main(String[] args) throws InterruptedException {
  2.     Thread thread = new Thread(new Runnable() {
  3.         @Override
  4.         public void run() {
  5.             for (int i = 1; i <= 10; i++) {
  6.                 // 打印 i 信息
  7.                 System.out.println("i:" + i);
  8.                 try {
  9.                     // 休眠 100 毫秒
  10.                     Thread.sleep(100);
  11.                 } catch (InterruptedException e) {
  12.                     e.printStackTrace();
  13.                 }
  14.             }
  15.         }
  16.     });
  17.     // 設(shè)置為守護(hù)線程
  18.     thread.setDaemon(true);
  19.     // 啟動(dòng)線程
  20.     thread.start();
  21.     // 等待線程執(zhí)行完
  22.     thread.join();
  23.     System.out.println("子線程==守護(hù)線程:" + thread.isDaemon());
  24.     System.out.println("主線程==守護(hù)線程:" + Thread.currentThread().isDaemon());
  25. }

以上程序執(zhí)行結(jié)果如下:

通過(guò)上述結(jié)果我們可以看出,即使是守護(hù)線程,當(dāng)程序中調(diào)用 join() 方法時(shí),程序依然會(huì)等待守護(hù)線程執(zhí)行完成之后再結(jié)束進(jìn)程。

5.守護(hù)線程應(yīng)用場(chǎng)景

守護(hù)線程的典型應(yīng)用場(chǎng)景就是垃圾回收線程,當(dāng)然還有一些場(chǎng)景也非常適合使用守護(hù)線程,比如服務(wù)器端的健康檢測(cè)功能,對(duì)于一個(gè)服務(wù)器來(lái)說(shuō)健康檢測(cè)功能屬于非核心非主流的服務(wù)業(yè)務(wù),像這種為了主要業(yè)務(wù)服務(wù)的業(yè)務(wù)功能就非常合適使用守護(hù)線程,當(dāng)程序中的主要業(yè)務(wù)都執(zhí)行完成之后,服務(wù)業(yè)務(wù)也會(huì)跟隨者一起銷(xiāo)毀。

6.守護(hù)線程的執(zhí)行優(yōu)先級(jí)

首先來(lái)說(shuō),線程的類(lèi)型(用戶(hù)線程或守護(hù)線程)并不影響線程執(zhí)行的優(yōu)先級(jí),如下代碼所示,定義一個(gè)用戶(hù)線程和守護(hù)線程,分別執(zhí)行 10 萬(wàn)次循環(huán),通過(guò)觀察最后的打印結(jié)果來(lái)確認(rèn)線程類(lèi)型對(duì)程序執(zhí)行優(yōu)先級(jí)的影響。

  
 
 
 
  1. public class DaemonExample {
  2.     private static final int count = 100000;
  3.     public static void main(String[] args) throws InterruptedException {
  4.         // 定義任務(wù)
  5.         Runnable runnable = new Runnable() {
  6.             @Override
  7.             public void run() {
  8.                 for (int i = 0; i < count; i++) {
  9.                     System.out.println("執(zhí)行線程:" + Thread.currentThread().getName());
  10.                 }
  11.             }
  12.         };
  13.         // 創(chuàng)建守護(hù)線程 t1
  14.         Thread t1 = new Thread(runnable, "t1");
  15.         // 設(shè)置為守護(hù)線程
  16.         t1.setDaemon(true);
  17.         // 啟動(dòng)線程
  18.         t1.start();
  19.         // 創(chuàng)建用戶(hù)線程 t2
  20.         Thread t2 = new Thread(runnable, "t2");
  21.         // 啟動(dòng)線程
  22.         t2.start();
  23.     }
  24. }

以上程序執(zhí)行結(jié)果如下:

通過(guò)上述結(jié)果可以看出,線程的類(lèi)型不管是守護(hù)線程還是用戶(hù)線程對(duì)程序執(zhí)行的優(yōu)先級(jí)是沒(méi)有任何影響的,而當(dāng)我們將 t2 的優(yōu)先級(jí)調(diào)整為最大時(shí),整個(gè)程序的運(yùn)行結(jié)果就完全不同了,如下代碼所示:

  
 
 
 
  1. public class DaemonExample {
  2.     private static final int count = 100000;
  3.     public static void main(String[] args) throws InterruptedException {
  4.         // 定義任務(wù)
  5.         Runnable runnable = new Runnable() {
  6.             @Override
  7.             public void run() {
  8.                 for (int i = 0; i < count; i++) {
  9.                     System.out.println("執(zhí)行線程:" + Thread.currentThread().getName());
  10.                 }
  11.             }
  12.         };
  13.         // 創(chuàng)建守護(hù)線程 t1
  14.         Thread t1 = new Thread(runnable, "t1");
  15.         // 設(shè)置為守護(hù)線程
  16.         t1.setDaemon(true);
  17.         // 啟動(dòng)線程
  18.         t1.start();
  19.         // 創(chuàng)建用戶(hù)線程 t2
  20.         Thread t2 = new Thread(runnable, "t2");
  21.         // 設(shè)置 t2 的優(yōu)先級(jí)為最高
  22.         t2.setPriority(Thread.MAX_PRIORITY);
  23.         // 啟動(dòng)線程
  24.         t2.start();
  25.     }
  26. }

以上程序執(zhí)行結(jié)果如下:

通過(guò)上述的結(jié)果可以看出,程序的類(lèi)型和程序執(zhí)行的優(yōu)先級(jí)是沒(méi)有任何關(guān)系,當(dāng)新創(chuàng)建的線程默認(rèn)的優(yōu)先級(jí)都是 5 時(shí),無(wú)論是守護(hù)線程還是用戶(hù)線程,它們執(zhí)行的優(yōu)先級(jí)都是相同的,當(dāng)將二者的優(yōu)先級(jí)設(shè)置不同時(shí),執(zhí)行的結(jié)果也會(huì)隨之改變(優(yōu)先級(jí)設(shè)置的越高,最早被執(zhí)行的概率也越大)。

7.總結(jié)

在 Java 語(yǔ)言中線程分為用戶(hù)線程和守護(hù)線程,守護(hù)線程是用來(lái)為用戶(hù)線程服務(wù)的,當(dāng)一個(gè)程序中的所有用戶(hù)線程都結(jié)束之后,無(wú)論守護(hù)線程是否在工作都會(huì)跟隨用戶(hù)線程一起結(jié)束。守護(hù)線程從業(yè)務(wù)邏輯層面來(lái)看權(quán)重比較低,但對(duì)于線程調(diào)度器來(lái)說(shuō)無(wú)論是守護(hù)線程還是用戶(hù)線程,在優(yōu)先級(jí)相同的情況下被執(zhí)行的概率都是相同的。守護(hù)線程的經(jīng)典使用場(chǎng)景是垃圾回收線程,守護(hù)線程中創(chuàng)建的線程默認(rèn)情況下也都是守護(hù)線程。


網(wǎng)站欄目:Java中用戶(hù)線程和守護(hù)線程區(qū)別這么大?
網(wǎng)站URL:http://www.5511xx.com/article/djgphsh.html