2012-09-18 110 views
0

我有一個運行方法的類,並且在類的主要方法定時器調用與該代碼的類:的ThreadPoolExecutor OutOfMemoryException異常

Timer timer = new Timer(); 
timer.scheduleAtFixedRate(new LegacySmsSender(), 0, 2*1000); 
在運行方法

,我聲明一個ThreadExecutorPool:

ThreadPoolExecutor packetProcessorThreadPool = 
     new ThreadPoolExecutor(4, 
           4, 
           Long.MAX_VALUE, 
           TimeUnit.DAYS, 
           new LinkedBlockingQueue<Runnable>(), 
           new MyThreadFactory("packetProcessorThreadPool") 
           ); 

我創建4個PacketProcessors與new PacketProcessor()packetProcessorThreadPool.submit並保持其Future返回一個列表。那我等他們都在一個循環中完成:

for(Future<?> f:packetProcessorList) 
{ 
    System.out.println("before f.get() "+new Date()); 
    f.get(); 
} 

而那些PacketProcessor類的run方法裏面,他們宣佈的ThreadPoolExecutor和創建和數量1-5000之間提交線程(其通常創建6-7線程),並在PacketProcessor的ThreadPoolExecutor的代碼是這樣的:

ThreadPoolExecutor commonThreadPool = 
     new ThreadPoolExecutor(
         20, 
         20, 
         Long.MAX_VALUE, 
         TimeUnit.DAYS, 
         new LinkedBlockingQueue<Runnable>(), 
         new MyThreadFactory("commonThreadPool")); 

,並在結束時,我跑了一段20分鐘,我檢查的VisualVM,我的內存使用情況和活動​​線程數量的增加,所有的時間。問題是什麼 ?

注:請毫不猶豫地問我要更多信息或問題

這裏是一些信息截圖:

enter image description here

編輯1:

我270 MB的堆轉儲。我發現了160MB的char []。我發現像1000-20000個查詢字符串。我使用StringBuilder構建查詢字符串。爲什麼他們沒有得到GCed?

回答

2

執行程序的目的是在應用程序啓動時重新聲明並重用。否則,您可能只需按需創建單個線程。如果在應用程序執行期間不斷創建新的執行程序,則它們的線程將保持運行狀態,因此線程數將繼續增加。

所以,只需使用DI框架創建執行程序並將它們注入到代碼中即可。或者如果它是一個小型項目,請將它們放在靜態字段中。

+0

我試圖使用它們作爲靜態,但它根本沒有改變這個分析器上的圖像。活動線程永不減少的原因是什麼? – kommradHomer

1
run方法

,我宣佈一個ThreadExecutorPool

如果你在被每2秒,你會得到許多線程在幾分鐘內執行run方法聲明ThreadExecutorPool。

+0

沒有。在run方法,我等待線程完成,所以計時器就不會第一個跑'LegacySmsSender'完成 – kommradHomer

+0

你有你的run方法這段代碼被執行定期?:的ThreadPoolExecutor packetProcessorThreadPool = 新的ThreadPoolExecutor(前再次啓動... – Chobicus

+0

這個代碼是在定時器執行 – kommradHomer

0

問題是,你已經告訴你所創建的所有ExecutorService是爲了創建線程,然後讓它們永遠活着。這是在代碼非常清楚地明顯:

new ThreadPoolExecutor(
         20, 
         20, 
         Long.MAX_VALUE, 
         TimeUnit.DAYS, 
         new LinkedBlockingQueue<Runnable>(), 
         new MyThreadFactory("commonThreadPool")); 

第三個和第四個參數基本上說「保持空閒線程活着(幾乎)無限的日子」。你做他們傳遞任務時的執行情況

  1. 呼叫ExecutorService.shutdown

    您可以在幾個方面解決這個問題。

  2. 最好的解決方案是使用單一的ScheduledExecutorService和更合理的任務分配邏輯來限制線程數量並通過阻止線程上下文切換提高性能。
+0

我嘗試了數字1的解決方案,並呼籲'shutdown'的熱塑性彈性體後,我等待的Future.get S IN的循環。我得到了線程執行的拒絕,然後我嘗試數字2,3和TIMEUNIT秒,它並沒有改變什麼在任何時候都不應該讓活線程數量減少? – kommradHomer

+0

如果你得到一個'RejectedExecutionException',然後你在任務被關閉後將任務提交給ExecutorService。隨意閱讀API。至於線程去,我錯了,直到線程池關閉,他們不會死,因爲他們是「核心線程」。 –

+0

既設置了「保留IDE線程活着3秒」,也關閉了'commonThreadPool',現在我設法有27個線程住在最大。它在19到27之間變化,但內存使用量仍在不斷增加 – kommradHomer

相關問題