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

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
面試突擊:什么是守護線程?它和用戶線程有什么區(qū)別?

想要查看線程到底是用戶線程還是守護線程,可以通過 Thread.isDaemon() 方法來判斷,如果返回的結(jié)果是 true 則為守護線程,反之則為用戶線程。

創(chuàng)新互聯(lián)專注于馬鞍山企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計,成都做商城網(wǎng)站。馬鞍山網(wǎng)站建設(shè)公司,為馬鞍山等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站制作,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

我們來測試一下默認情況下線程和線程池屬于哪種線程類型?測試代碼如下:

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
* 線程類型:守護線程 OR 用戶線程
*/
public class ThreadType {
public static void main(String[] args) {
// 創(chuàng)建線程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//...
}
});
// 創(chuàng)建線程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 10,
0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("ThreadPool 線程類型:" +
(Thread.currentThread().isDaemon() == true ? "守護線程" : "用戶線程"));
}
});
System.out.println("Thread 線程類型:" +
(thread.isDaemon() == true ? "守護線程" : "用戶線程"));
System.out.println("main 線程類型:" +
(Thread.currentThread().isDaemon() == true ? "守護線程" : "用戶線程"));
}
}

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

從上述結(jié)果可以看出,默認情況下創(chuàng)建的線程和線程池都是用戶線程。

守護線程定義

守護線程(Daemon Thread)也被稱之為后臺線程或服務(wù)線程,守護線程是為用戶線程服務(wù)的,當程序中的用戶線程全部執(zhí)行結(jié)束之后,守護線程也會跟隨結(jié)束。守護線程的角色就像“服務(wù)員”,而用戶線程的角色就像“顧客”,當“顧客”全部走了之后(全部執(zhí)行結(jié)束),那“服務(wù)員”(守護線程)也就沒有了存在的意義,所以當一個程序中的全部用戶線程都結(jié)束執(zhí)行之后,那么無論守護線程是否還在工作都會隨著用戶線程一塊結(jié)束,整個程序也會隨之結(jié)束運行。

創(chuàng)建守護線程

我們可以通過 Thread.setDaemon(true) 方法將線程設(shè)置為守護線程,比如以下代碼的實現(xiàn):

public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//...
}
});
// 設(shè)置線程為守護線程
thread.setDaemon(true);
System.out.println("Thread 線程類型:" +
(thread.isDaemon() == true ? "守護線程" : "用戶線程"));
System.out.println("main 線程類型:" +
(Thread.currentThread().isDaemon() == true ? "守護線程" : "用戶線程"));
}

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

將線程池設(shè)置為守護線程

要把線程池設(shè)置為守護線程相對來說麻煩一些,需要將線程池中的所有線程都設(shè)置成守護線程,這個時候就需要使用線程工廠 ThreadFactory 來設(shè)置了(線程池中的所有線程都是通過線程工廠創(chuàng)建的),它的具體實現(xiàn)代碼如下:

public static void main(String[] args) throws InterruptedException {
// 線程工廠(設(shè)置守護線程)
ThreadFactory threadFactory = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// 設(shè)置為守護線程
thread.setDaemon(true);
return thread;
}
};
// 創(chuàng)建線程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 10,
0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), threadFactory);
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("ThreadPool 線程類型:" +
(Thread.currentThread().isDaemon() == true ? "守護線程" : "用戶線程"));
}
});
Thread.sleep(2000);
}

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

守護線程 VS 用戶線程

通過前面的內(nèi)容我們了解了什么是用戶線程和守護線程了,那二者有什么區(qū)別呢?接下來我們用一個小示例來觀察一下。接下來我們將創(chuàng)建一個線程,分別將這個線程設(shè)置為用戶線程和守護線程,在每個線程中執(zhí)行一個 for 循環(huán),總共執(zhí)行 10 次信息打印,每次打印之后休眠 100 毫秒,來觀察程序的運行結(jié)果。

用戶線程

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

public static void main(String[] args) throws InterruptedException {
// 創(chuàng)建用戶線程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
// 打印 i 信息
System.out.println("i:" + i);
try {
// 休眠 100 毫秒
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
// 啟動線程
thread.start();
}

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

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

守護線程

public static void main(String[] args) throws InterruptedException {
// 創(chuàng)建守護線程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
// 打印 i 信息
System.out.println("i:" + i);
try {
// 休眠 100 毫秒
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
// 設(shè)置為守護線程
thread.setDaemon(true);
// 啟動線程
thread.start();
}

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

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

守護線程注意事項

守護線程的設(shè)置 setDaemon(true) 必須要放在線程的 start() 之前,否則程序會報錯。也就是說在運行線程之前,一定要先確定線程的類型,并且線程運行之后是不允許修改線程的類型的。接下來我們來演示一下,如果在程序運行執(zhí)行再設(shè)置線程的類型會出現(xiàn)什么問題?演示代碼如下:

public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
// 打印 i 信息
System.out.println("i:" + i + ",isDaemon:" +
Thread.currentThread().isDaemon());
try {
// 休眠 100 毫秒
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
// 啟動線程
thread.start();
// 設(shè)置為守護線程
thread.setDaemon(true);
}

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

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

總結(jié)

在 Java 語言中線程分為兩類:用戶線程和守護線程,默認情況下我們創(chuàng)建的線程或線程池都是用戶線程,守護線程是為用戶線程服務(wù)的,當一個程序中的所有用戶線程都執(zhí)行完成之后程序就會結(jié)束運行,程序結(jié)束運行時不會管守護線程是否正在運行,由此我們可以看出守護線程在 Java 體系中權(quán)重是比較低的,這就是守護線程和用戶線程的區(qū)別。

本文轉(zhuǎn)載自微信公眾號「Java面試真題解析」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Java面試真題解析公眾號。


文章標題:面試突擊:什么是守護線程?它和用戶線程有什么區(qū)別?
標題網(wǎng)址:http://m.5511xx.com/article/cogccpe.html