2013-09-29 164 views
0

我正在改變線程池執行程序的傳統設計。具體如下: -線程池執行程序

遺留: - 在傳統設計的情況下,在應用程序啓動時創建600個線程。 ,並放置在各種池中,然後在需要時拾取並將任務分配給相應的線程。

新: - 在新的設計我換成執行服務線程池

ThreadPoolExecutor thpool = new ThreadPoolExecutor(coreSize,poolsize,...); 

我所觀察到的是,在執行程序的情況下,在啓動時創建的螺紋。它們是在客戶端發起請求時創建的。由於內存中創建的線程與前一個線程相比較少。

但我的問題是這是正確的方式,因爲線程創建也是在觸發時發生的開銷。

請告訴哪一個更重,進程在客戶端調用時創建線程或根據傳統方法在內存中存在空閒線程。

還建議使用哪個執行程序池以便在性能方面獲得最佳結果。

回答

1

固定在啓動時600級的線程,嘗試使用java.util.concurrent.Executors.newFixedThreadPool(600);

創建一個可重用操作 關閉不受限制的隊列線程固定數量的線程池。在任何時候,最多nThreads線程 將被激活的處理任務。如果在所有線程處於活動狀態時提交了其他任務 ,則他們將在隊列中等待,直到 線程可用。如果任何線程在關閉之前執行 期間因失敗而終止,則在需要 執行後續任務時將取代它。池中的線程將一直存在,直到 它被明確關閉。

正如您所看到的,文檔不會告訴我們線程是立即啓動還是按需啓動。

如果你想絕對是600個線程開始啓動時,你可以張貼600項空任務:

for(int i = 0; i < 600; ++i) { 
    executor.submit(new Runnable(){public void run(){/**/}}); 
} 
0

您可以撥打:

thpool.prestartAllCoreThreads(); 

thpool.prestartCoreThread(); 

這兩種方法啓動一個核心線程(線程),導致它閒置地等待工作。

但我建議不要這樣做,這將是你的資源頭頂。

0

600聽起來很多。您可能需要稍微降低這個數量,以適應​​可用處理器的數量。或者,如果線程最終等待很長時間,則平均負載的因素是TPE的Runnables,如果您的線程不是100%CPU限制的話。假設你有nCPUs=Runtime.getRuntime().availableProcessors()loadFactor作爲你的線程的平均負載(如在測試中觀察到的,或者更好的是連續監測)。然後你會使用nThreads = nCPUs/loadFactor,並希望loadFactor不爲零。

你也可以使用更小的內核大小和更大的池大小,但是你需要一個有界的隊列。在這種情況下,如果隊列已滿,TPE將啓動新線程,直到達到池大小。如果大部分工作都是在內核中處理的,那麼線程創建不應該太頻繁,並且開銷不應該成爲問題。但即便如此,TPE最大線程運行時也可能最終阻塞。

如果您的工作是某種傳入工作,例如從不能阻塞的其他連接的套接字中讀取,您可以創建一個無限制的中間隊列,以便在TPE中最終阻止入站處理,並使用另一個線程將作業從中間提交到TPE隊列。

+0

我們如何計算需要的線程數量?猜測我們有一個公式: - CPU數量*性能吞吐量*(1 + W/C)其中W是等待時間,C是所需的計算時間。 請詳細告訴我如何獲得所需的線程數。 – Scientist

+0

不確定你的_Performance throughput_是什麼,但看到我的編輯。 –

+0

Hi Ralf, 感謝您的意見。那麼,但我已經進入修復。 我創建了一個ThreadPoolExecutor,其核心大小爲maxpoolsize/5,並使用LinkedBlockingQueue作爲隊列。 我已經調用了方法「prestartAllCoreThreads」,它在啓動時啓動大約170個線程的所有核心線程。 – Scientist