根據Brian Goetz的Java Concurrency in Practice 在所有(非守護進程)線程終止前,JVM無法退出,因此未能關閉Executor可能會阻止JVM退出。如何在退出應用程序時關閉所有執行程序?
即,如果有Executors,System.exit(0)不一定像預期的那樣工作。看起來有必要對所有包含執行程序的類添加某種類型的方法,然後在應用程序即將終止時調用它們。這是唯一的方法,還是有某種快捷方式來關閉所有的執行程序?
根據Brian Goetz的Java Concurrency in Practice 在所有(非守護進程)線程終止前,JVM無法退出,因此未能關閉Executor可能會阻止JVM退出。如何在退出應用程序時關閉所有執行程序?
即,如果有Executors,System.exit(0)不一定像預期的那樣工作。看起來有必要對所有包含執行程序的類添加某種類型的方法,然後在應用程序即將終止時調用它們。這是唯一的方法,還是有某種快捷方式來關閉所有的執行程序?
沒有捷徑可以做到這一切,沒有。此外,您應該撥打shutdownNow()
而不是shutdown()
,否則您可能會等待一段時間。
我想你應該做的是在創建Executor時將其註冊到中心位置。然後,在關閉時,只需在該中央對象上調用shutdown()
,這又可以終止每個註冊的執行程序。
如果您使用Spring,那麼您可以利用其工廠bean來創建和管理執行程序。這包括在應用程序退出時優雅地關閉它們,並節省您自己管理它們。
中央登記冊似乎是一個合理的選擇。有趣的是,java.util.concurrent不包括這樣的。 – 2009-07-31 10:11:09
Executors只是一堆靜態信息,這使得很難將其隱藏在註冊界面後面而不復制數十個方法簽名,這也是一個恥辱。 – skaffman 2009-07-31 10:16:24
也許他的意思是說,JVM不能自行停止,直到nondaemon線程完成。它像從Java SomeClass這樣的命令運行一個簡單的類,並在執行main方法JVM後停止。
System.exit是JVM終止命令,即使守護程序線程正在運行,JVM也會關閉。
正如Goetz寫道,* nondaemon *線程可以阻止JVM退出。其實我已經經歷過這個。調試器顯示該應用程序可能會阻塞到系統。無限地退出(0),但它似乎是不確定的行爲。通常它不會阻塞,但有時它會阻塞。 – 2009-07-31 10:06:33
您還可以提供一個ThreadFactory實現,將創建的線程標記爲守護線程。我更喜歡一個乾淨的關閉機制(使用生命週期方法),但有些情況下,如果適當,您不需要保證未完成任務的狀態/完成。
默認情況下,執行程序將只創建非守護程序線程。您可以通過向Executor提供您自己的ThreadFactory來覆蓋它。這裏有一個例子:
class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
要謹慎,但是,因爲JVM將退出馬上即使這些線程都在忙着做無用功!
裝飾執行人與com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService
@Beta
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor,
long terminationTimeout,
TimeUnit timeUnit)
給定的ThreadPoolExecutor轉換到應用程序完成時離開一個ExecutorService的。它通過使用守護程序線程並添加關閉掛鉤來等待它們完成。
這主要是針對固定線程池。請參閱Executors.newFixedThreadPool(int)。
我很懷疑Executor和Runnable。我刪除了我的答案,因爲它沒有多大意義。 @skaffman有我的投票。 – 2009-07-31 10:26:00