2016-09-29 153 views
3

考慮下面的Java代碼的Java newSingleThreadExecutor垃圾收集

void doSomething(Runnable r1, Runnable r2){ 
    Executor executor = Executors.newSingleThreadExecutor(); 
    executor.execute(r1); 
    executor.execute(r2); 
} 

當我調用DoSomething的方法,執行程序已創建並在其他以後執行任務r1和r2順序之一。

我的問題是:一旦兩個任務r1和r2終止會發生什麼?

我想執行人對象將是垃圾回收,但我不知道是否也將關閉。如果執行程序爲其執行創建新線程,該線程是否會導致資源泄漏?

+1

您可以使用ExecutorService,然後在您提交執行任務後調用shutdown。 ES將在結束之前等待任務完成。 – Jacob

+0

您還可以使用帶有零核心線程的'ThreadPoolExecutor',以便在沒有要運行的任務時回收線程。 – Magnus

回答

5

我想執行器對象會被垃圾收集,但是我不知道它是否會被關閉。

其實Executors.newSingleThreadExecutor()木下創建一個FinalizableDelegatedExecutorService實例,它將呼籲finalizeshutdown表明它正在收集垃圾時,將自動關機。

但是,我不認爲依賴它是一個好主意,因爲它更多地是一個實現細節,可能會從一個版本更改爲另一個版本,您應該更確切地關閉它,以防止任何意外的錯誤。

+0

您是否有任何提及FinalizableDelegatedExecutorService實例被創建的事實? – ichfarbstift

+0

是這裏http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/concurrent/Executors.java#Executors.newSingleThreadExecutor%28%29 –

+1

@ ichfarbstift代碼。但是,代碼的這方面不能通過「合同」來保證,所以不要依賴它。在你的'ExecutorService'引用丟失之前調用'shutdown()'。並且請注意,即使調用了shutdown(),「ExecutorService」也會運行,直到以前提交的任務完成。 – erickson

3

ExecutorService的文檔,我們可以讀

「未使用的ExecutorService應該被關閉,以允許 其資源回收。」

基本上,您將不得不手動終止執行程序服務。雖然執行程序對象本身將被垃圾回收,但內部線程不會。如果該對象不是由GC根引用

+0

內部線程不會?這讓我非常驚訝。 – erickson

+0

創建的線程具有對它們運行的​​「ExecutorService」的引用。只要它們處於活動狀態,「ExecutorService」就不符合GC的條件。 –

+0

@erickson如果你的代碼失去對'ExecutorService'的引用,那麼文檔不會承諾會發生任何特別的事情,並且它會警告你,如果你想要回收「資源」,應該關閉它。如果你想要你的代碼「隨處運行」,那麼你可能應該相信javadoc所說的,而不是假設javadoc沒有提供什麼。 –

0

對象只能GC'd。什麼是GC根?最常見的是System類和一個正在運行的線程。 ExecutorService將創建並維護正在運行的線程,因此即使ES在方法中創建,ES仍然可以訪問而不是GC'd。

正如其他人提及,您將需要關閉ES它被GC'd。