2016-09-29 253 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。