2013-01-11 54 views
7

我在Java中使用Executors框架爲多線程應用程序創建線程池,並且我有一個與性能相關的問題。使用Executors服務以Java創建固定大小線程池的最佳方式

我有一個應用程序可以實時或非實時模式工作。在情況下,它的實時,我只是使用下列內容:

THREAD_POOL = Executors.newCachedThreadPool(); 

但如果它不是實時的,我想控制我的線程池的大小的能力。 要做到這一點,我在考慮2個選項,但我並不真正瞭解它們之間的差異,哪個更好。

選項1是使用簡單的方法:

THREAD_POOL = Executors.newFixedThreadPool(threadPoolSize); 

選擇2是創建自己的ThreadPoolExecutor這樣的:

RejectedExecutionHandler rejectHandler = new RejectedExecutionHandler() { 
@Override 
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { 
    try { 
     executor.getQueue().put(r); 
    } catch (Exception e) {} 
} 
};   
THREAD_POOL = new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(10000), rejectHandler); 

我想了解什麼是使用的優點更復雜的選項2,以及如果我應該使用另一個數據結構而不是LinkedBlockingQueue?任何幫助,將不勝感激。

回答

13

查看源代碼,你會認識到:

Executors.newFixedThreadPool(threadPoolSize); 

相當於到:

return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, MILLISECONDS, 
           new LinkedBlockingQueue<Runnable>()); 

因爲它不提供明確的RejectedExecutionHandler,默認AbortPolicy使用。一旦隊列滿了,基本上會拋出RejectedExecutionException。但是隊列是無限的,所以它永遠不會滿。因此這個執行者接受任務的數量。

你的聲明要複雜得多,並完全不同:

  • new LinkedBlockingQueue<Runnable>(10000)將導致線程池如果超過10000正在等待放棄任務。

  • 我不明白你的RejectedExecutionHandler在做什麼。如果池發現它不能將更多的可運行對象放入隊列,它會調用你的處理程序。在這個處理程序中,您...嘗試再次將該Runnable放入隊列中(這將使在99%的案例塊中失敗)。最後你吞下例外。好像ThreadPoolExecutor.DiscardPolicy就是你以後的樣子。

    看下面你的評論似乎是你試圖阻止或以某種方式節制客戶端,如果任務隊列太大。我不認爲RejectedExecutionHandler內部阻擋是一個好主意。反而考慮CallerRunsPolicy拒絕政策。不完全一樣,但足夠接近。

總結:如果你想限制未決任務的數量,你的方法幾乎是好的。如果你想限制併發線程的數量,第一個單行就足夠了。

1 - 假設2^31是無窮大

+0

的'RejectedExecutionHandler'實際上阻塞,調用'executor.getQueue()把(R);'將阻塞,直到隊列中釋放,所以。最後,我的處理程序允許保留有界的隊列而不中止任何任務。除非我錯了。 +1的其他細節。 –

+0

@CharlesMenguy:謝謝你澄清,我的壞,我會更新我的問題。但是你想通過在'RejectedExecutionHandler'裏面阻塞來實現什麼?我相信它可能會有一些非常意想不到的副作用,例如阻塞調用者線程。也許你需要'CallerRunsPolicy'? –

+0

實際上,在看完它之後,'CallerRunsPolicy'聽起來真的很有希望做我想做的事,我會試一試謝謝!也許你可以在答案中加上,我會接受你的答案。 –

相關問題