Cra*_*lin 31 java concurrency garbage-collection
在此代码示例中,ExecutorService使用了一个并允许超出范围.
public static void main(String[] args)
{
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.submit(new Runnable()
{
public void run()
{
System.out.println("hello");
}
});
}
Run Code Online (Sandbox Code Playgroud)
一旦executorService超出范围,就应该收集并最终确定.ThreadPoolExecutor中的finalize()方法调用shutdown().
/**
* Invokes {@code shutdown} when this executor is no longer
* referenced and it has no threads.
*/
protected void finalize() {
shutdown();
}
Run Code Online (Sandbox Code Playgroud)
调用shutdown()后,池线程应终止,并允许JVM退出.但是,执行程序服务永远不会被收集,因此JVM保持活动状态.甚至对System.gc()的调用似乎也不起作用.为什么即使在main()终止后,executorService也没有被收集?
注意:我知道我应该自己调用shutdown(),而且我总是在测试之外做.我很好奇为什么最终确定不作为备份在这里工作.
Aff*_*ffe 50
这与GC不确定无关,但它没有帮助!(这是你的例子中的一个原因,但即使我们"修复它"以消耗内存并强制收集,它仍然无法完成)
执行程序创建的Worker线程是内部类,它们具有对执行程序本身的引用.(他们需要它能够看到队列,runstate等等!)运行线程不是垃圾收集的,所以当池中的每个线程都有该引用时,它们将使执行器保持活动状态直到所有线程都死亡.如果您不手动执行某些操作来停止线程,它们将永远保持运行,您的JVM将永远不会关闭.
mjt*_*mjt 20
情感是正确的; 线程池的线程将阻止它被垃圾收集.当您调用Executors.newFixedThreadPool(3)时,您将获得如此构造的ThreadPoolExecutor:
ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
Run Code Online (Sandbox Code Playgroud)
如果您阅读了ThreadDoolExecutor的JavaDoc,它会说:
程序中不再引用且没有剩余线程的池将自动关闭.如果您希望确保即使用户忘记调用shutdown()也会回收未引用的池,那么您必须 通过设置适当的保持活动时间,使用零核心线程的下限和/或来安排未使用的线程最终死亡设置allowCoreThreadTimeOut(boolean).
如果你想让你的线程池像你期望的那样完成,你应该做其中的一件事.
| 归档时间: |
|
| 查看次数: |
10605 次 |
| 最近记录: |