2017-09-02 168 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每個任務執行後自動完成所有必要的清潔。但它只能清理自己的記憶。在任務執行期間創建的對象是程序員的責任。如果內存在任務執行後增長,則意味着有引用可以執行創建的任務或者在程序中某處執行任務。

相關問題