2009-07-31 98 views
9

根據Brian Goetz的Java Concurrency in Practice 在所有(非守護進程)線程終止前,JVM無法退出,因此未能關閉Executor可能會阻止JVM退出。如何在退出應用程序時關閉所有執行程序?

即,如果有Executors,System.exit(0)不一定像預期的那樣工作。看起來有必要對所有包含執行程序的類添加某種類型的方法,然後在應用程序即將終止時調用它們。這是唯一的方法,還是有某種快捷方式來關閉所有的執行程序?

+0

我很懷疑Executor和Runnable。我刪除了我的答案,因爲它沒有多大意義。 @skaffman有我的投票。 – 2009-07-31 10:26:00

回答

14

沒有捷徑可以做到這一切,沒有。此外,您應該撥打shutdownNow()而不是shutdown(),否則您可能會等待一段時間。

我想你應該做的是在創建Executor時將其註冊到中心位置。然後,在關閉時,只需在該中央對象上調用shutdown(),這又可以終止每個註冊的執行程序。

如果您使用Spring,那麼您可以利用其工廠bean來創建和管理執行程序。這包括在應用程序退出時優雅地關閉它們,並節省您自己管理它們。

+0

中央登記冊似乎是一個合理的選擇。有趣的是,java.util.concurrent不包括這樣的。 – 2009-07-31 10:11:09

+0

Executors只是一堆靜態信息,這使得很難將其隱藏在註冊界面後面而不復制數十個方法簽名,這也是一個恥辱。 – skaffman 2009-07-31 10:16:24

0

也許他的意思是說,JVM不能自行停止,直到nondaemon線程完成。它像從Java SomeClass這樣的命令運行一個簡單的類,並在執行main方法JVM後停止。

System.exit是JVM終止命令,即使守護程序線程正在運行,JVM也會關閉。

+1

正如Goetz寫道,* nondaemon *線程可以阻止JVM退出。其實我已經經歷過這個。調試器顯示該應用程序可能會阻塞到系統。無限地退出(0),但它似乎是不確定的行爲。通常它不會阻塞,但有時它會阻塞。 – 2009-07-31 10:06:33

5

您還可以提供一個ThreadFactory實現,將創建的線程標記爲守護線程。我更喜歡一個乾淨的關閉機制(使用生命週期方法),但有些情況下,如果適當,您不需要保證未完成任務的狀態/完成。

7

默認情況下,執行程序將只創建非守護程序線程。您可以通過向Executor提供您自己的ThreadFactory來覆蓋它。這裏有一個例子:

class DaemonThreadFactory implements ThreadFactory { 
    public Thread newThread(Runnable r) { 
    Thread t = new Thread(r); 
    t.setDaemon(true); 
    return t; 
    } 
} 

要謹慎,但是,因爲JVM將退出馬上即使這些線程都在忙着做無用功!

8

裝飾執行人與com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService

@Beta 
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, 
             long terminationTimeout, 
             TimeUnit timeUnit) 

給定的ThreadPoolExecutor轉換到應用程序完成時離開一個ExecutorService的。它通過使用守護程序線程並添加關閉掛鉤來等待它們完成。

這主要是針對固定線程池。請參閱Executors.newFixedThreadPool(int)。

相關問題