2013-04-10 68 views
0

我們正在使用通過ExecutorService#newCachedThreadPool創建的CachedThreadPool。 (Java 1.6)。我們在代碼中的其他地方發現錯誤:「無法創建新的本地線程」,我們診斷爲內存不足問題。當這個問題發生時,我們調用提交的代碼塊(我們使用提交,不執行)會變慢。我們懷疑ThreadPool在嘗試創建新線程來處理任務時遇到了「無法創建新的本地線程」的相同問題,但我們無法確定。從(ExecutorService)捕獲異常CachedThreadPool

有沒有辦法趕上從ExecutorService的內部異常? 爲了100%清楚,我不是在談論給予ExecutorService的任務,而是從ExecutorService本身。

+0

也許你應該做一個線程轉儲和看到所有的線程會。這不應該發生。 – 2013-04-10 23:25:31

+0

這絕對是一個系統負載問題。我得到它不應該去。這是由於下游的依賴性失敗以及我們在我們這邊嘗試了邏輯。線程全部排隊等待重試。 – 2013-04-11 21:14:19

回答

2

Executors.newCachedThreadPool創建一個具有無限的最大線程池大小(注意ThreadPoolExecutor構造函數的第二個參數)一ThreadPoolExecutor

public static ExecutorService newCachedThreadPool() { 
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 
            60L, TimeUnit.SECONDS, 
            new SynchronousQueue<Runnable>()); 
} 

這意味着,如果你在提交任務比消耗速度較快,新主題將是爲每個新任務創建,最終達到系統限制並引發「無法創建新的本地線程」異常。

要解決這個問題,您需要更改的ThreadPoolExecutor配置:

  1. 使用合理的ThreadPoolExecutor。
  2. 選擇一個適當的拒絕策略時,ThreadPoolExecutor耗盡。

例如:

ExecutorService executorService = new ThreadPoolExecutor(5,200, 
          60L, TimeUnit.SECONDS, 
          new ArrayBlockingQueue(1000), 
          Executors.defaultThreadFactory(), 
          new ThreadPoolExecutor.CallerRunsPolicy()); 

請閱讀JavaDocs詳細的配置信息。

+0

謝謝。我一直在挖掘文檔,並得到它爲什麼會發生,但我想知道是否有任何方法來捕捉錯誤?我是否必須編寫自己的ThreadFactory? – 2013-04-11 21:15:10

+0

@JohnHinnegan我不明白你爲什麼想要發現錯誤。我認爲使用長時間運行任務的無限制池大小的線程池是錯誤的設計。 – ericson 2013-04-12 02:21:02

+0

他們沒有長時間運行。我並不認爲一個無限的游泳池是有風險的或者顯然是錯誤的。但是,如果主機上的其他內容正在啓動,則固定池可能會出現此問題。我試圖在我的系統中構建健壯的監控,並且這個錯誤在我們的系統的一部分中突然出現並且未被發現。我知道這是錯誤,因爲我們在其他地方發現了它(顯然它對JVM來說是全局的)。當你回答的時候,我並沒有注意到RejectedExecutionHandler是什麼。我認爲這回答了我的問題。我想我可以實現其中的一個來處理異常。 – 2013-04-12 13:43:55

0

你可以使用實現Runnable接口的自定義類excpetions的集合內,像這樣:

public class MyRunnable implements Runnable { 
    private List<Exception> exceptions; 

    ... 

    public void addException(Exception e) { ... } 
    public void getExceptions(){ ... } 
} 

所有可運行後完成自己的執行,你可以檢查它們內部異常,並拋出另一個異常響應。