Thread類方法之三--setDaemon

主線程與守護線程

  • 默認情況下,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 命令後,不會等待它們處理完當前請求。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章