簡體   English   中英

在守護程序線程未完成之前,JVM不會退出

[英]JVM not exiting until daemon thread not completed

我只是偶然發現了守護程序線程的奇怪行為,我無法解釋。 我已將代碼縮減為最小,完整且可驗證的樣本:

public static void main(String[] args) throws InterruptedException {

    Thread runner = new Thread(() -> {

        final int SIZE = 350_000;
        for (int i = 0; i < SIZE; i++) {
            for (int j = i + 1; j < SIZE; j++) {
                if (i*j == SIZE * SIZE - 1) {
                    return;
                }
            }
        }
    });

    runner.setDaemon(true);
    runner.start();

    // Thread.sleep(1000);
    System.out.println("Exiting.");
}

runner線程執行的代碼大約需要12秒來終止我的盒子,我們對它的作用不感興趣,因為我只需要花一些時間來計算。

如果此片段按原樣運行,它將按預期工作:它在啟動后終止。 如果我取消注釋Thread.sleep(1000)行並運行程序,它可以工作大約12秒,然后打印出“退出”並終止。

據我了解線程如何守護工作,我希望這個代碼1秒鍾運行,然后終止執行,因為只有用戶線程運行的是一個與main()方法展開(該runner是一個后台守護線程)一旦1000毫秒通過,它就會到達執行結束,JVM應該停止。 此外,看起來很奇怪“退出”僅在12秒后打印,而不是在程序啟動時打印。

我錯了嗎? 如何實現所需的行為(暫停一秒然后停止,獨立於跑步者線程正在做什么)?

我在Linux機器上使用64位Oracle JDK 1.8.0_112,如果從IDE或命令行啟動它也具有相同的行為。

謝謝,安德烈

這可能是計數循環優化的結果,它從嵌套循環中刪除了安全點輪詢。 嘗試將-XX:+UseCountedLoopSafepoint標志添加到JVM啟動選項。

Thread#sleep(long)在從主方法返回之前暫停主線程(即在JVM考慮完成程序之前,只要沒有非deamon線程處於活動狀態)。 然后,調度程序可以自由運行任何其他可運行的線程,該線程將是deamon線程。 就目前而言,沒有明顯的理由讓JVM在完成執行之前強行搶占deamon線程以繼續在主線程中(它已經完成了休眠),因此JVM可以自由地繼續它的調度。 但是,它可以隨時選擇暫停正在運行的線程並安排另一個可運行的線程執行,因此不能保證您的示例的可重現性。

您可以通過在循環中插入對Thread#yield()#sleep(1)調用來強制執行搶占。 我敢打賭,你會開始看到片段在完成循環之前更快地退出。

有關線程狀態和調度的更多信息,可以在這里找到一個很好的概述。

更新評論:

我不能修改后台線程中的代碼(這是一個要求),所以我想找到一種方法來阻止它,如果它需要太長時間(我正在做的描述是stackoverflow.com/questions/41226054 / ...) 。

從法律上講,只能從內部停止正在運行的線程 ,因此通常每次迭代都會測試一個中止條件,如果滿足條件,則run方法return; 秒。 中止條件可以像從外部設置的布爾標志一樣簡單(! volatile警告 !)。 因此,最簡單的解決方案是讓主線程在睡眠后設置這樣的標志。

另一種可能是使用支持超時的ExecutorService ,請參閱問答以獲取涉及ScheduledExecutorService的示例。

我仍然不明白調度程序如何決定在運行System.out指令之前等待12秒。

它不會等待 12秒,它讓deamon線程運行完成,因為在判斷是否可以安全地停止JVM時,deamon只對JVM有用。 對於調度程序,只有線程的狀態很重要並且就其所關注的而言,在主線程的1s睡眠之后,它具有運行(deamon)和可運行的線程(main),並且沒有指示正在運行的線程應該暫停支持runnable線程。 切換線程在計算上也很昂貴,因此調度程序可能不願意缺少任何指示。 切換的指示可能是睡眠和產量,但GC運行和許多其他事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM