2017-09-02 521 views
1

考虑基本fixed线程池:执行程序创建的线程池是否释放内存?

Executors.newFixedThreadPool(MaxListeners) 

我打算不断提出新的任务 - 在响应传入TCP套接字服务请求。

但是,当每个任务的Runnable代码完成时 - 他们消耗的内存是而不是发布?我看到不断增长的jvm内存使用情况。

该应用程序倾向于按组处理一组任务。我们可以看到楼梯内存使用模式:在每一组任务之后,内存都是几十兆字节。等待几十分钟(到几个小时)不会导致内存被回收。

所以两个问题:

  • 是否有回收Executors线程池的存储器的手段不关闭池下
  • 如果不是,那么如何才能长期运行的线程池使用现有的java.util[.concurrent]包进行设计?
+0

问题可能与您的应用程序的实施方式有关。你没有尝试堆快照并分析它(使用JProfiler或YourKit)吗? – hunter

+0

一旦执行完成,Runnables应该完全符合GC的条件。 (如果Runnable使用任何ThreadLocal存储,这是一个不同的故事。)尽管如此,GC很可能不会立即收集Runnable。 –

+0

@hunter我花了很多时间与''jvisualvm'等jstat' – javadba

回答

1

Java中的对象不会被垃圾收集,直到没有引用留给那些对象。不要将此视为线程问题,而应视为对象引用问题。也就是说,找出哪些生物仍然参考这些数据。

幸运的是有工具可以帮助你做到这一点。您可以使用分析器来检查哪些对象仍然存在,甚至可以获取有关这些对象的数据。附件是Netbeans IDE中的默认分析器的示例。它正在分析我的应用程序并显示所有生活时间轴对象(这就是我所关注的)。但它可以很容易地向我展示所有物体。这是查看哪些对象导致内存泄漏或保持活动时间过长的快速方法。

enter image description here

编辑:请注意,@JBNIzet指出。

即使仍然存在对它们的引用,也可以对对象进行GC处理。重要的是,如果从GC根(线程堆栈或静态变量)引用强对象的链。

这是非常重要的注意事项,因为如果所有对该对象的引用都需要消失,大多数事情永远不会被清理干净。

+1

它可能不是你真正的意思,但“直到没有留给那些对象的引用”是完全错误的。即使仍然有对象的引用,对象*可以被GCCed。如果有字符串引用从GC根(线程堆栈或静态变量)的对象链重要的是。 –

+0

@JBNizet是的,感谢结算,最多。将编辑我的答案。 –

0

的ThreadPoolExecutor每个任务执行后自动完成所有必要的清洁。但它只能清理自己的记忆。在任务执行期间创建的对象是程序员的责任。如果内存在任务执行后增长,则意味着有引用可以执行创建的任务或者在程序中某处执行任务。

相关问题