主線程與守護線程
- 默認情況下,Java 進程需要等待所有線程都運行結束,纔會結束。
- 有一種特殊的線程叫做守護線程,只要其它非守護線程運行結束了,即使守護線程的代碼沒有執行完,也會強制結束。
Thread有一個setDeamon
方法,將當前線程設置爲守護線程,其中daemon
是一個boolean值,通過源碼我們發現,他會先通過isAlive
方法判斷線程的狀態。
- 簡單介紹一下
isAlive
方法:判斷當前的線程是否處於活動狀態。活動狀態是指線程已經啓動且尚未終止,線程處於正在運行(Running)或就緒(Runnable)的狀態,就認爲線程是存活的。
如果線程已經運行起來再調用這個方法,會拋出異常,所以setDeamon
一定要寫在start
方法前。
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
我們可以通過java進程是否結束判斷線程是否全部結束。
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
break;
}
}
log.debug("結束");
}, "t1");
// t1.setDaemon(true);
t1.start();
Thread.sleep(1000);
log.debug("結束");
}
}
/*Output:
16:55:07.072 c.Test15 [main] - 結束
*/
運行上例會發現當主線程結束後,t1線程仍然繼續運行,此時java進程也繼續運行。
如果此時把t1設置成守護進程
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
break;
}
}
log.debug("結束");
}, "t1");
t1.setDaemon(true);
t1.start();
Thread.sleep(1000);
log.debug("結束");
}
}
/*Output:
17:01:46.975 c.Test15 [main] - 結束
Process finished with exit code 0
*/
t1線程在mian線程結束後也自動結束,此時java進程也會結束。
守護線程應用
- 垃圾回收器線程就是一種守護線程;
- Tomcat 中的 Acceptor 和 Poller 線程都是守護線程,所以 Tomcat 接收到 shutdown 命令後,不會等待它們處理完當前請求。