2009-06-22 33 views
16

在Java中創建FixedThreadPool Executor對象時,您需要傳遞一個參數,描述Executor可以同時執行的線程數。我正在建立一個服務類,負責處理大量的電話號碼。對於每個需要執行Web服務的電話號碼(這是我的瓶頸),然後將響應保存在散列表中。運行Web服務請求的線程池的合理線程數

爲了使這個瓶頸對我的服務的性能不那麼有害,我決定創建Worker類來獲取未處理的元素並對它們進行處理。 Worker類實現Runnable接口,並使用Executor運行Workers。

可以在同一時間運行的工人數取決於Executor FixedThreadPool的大小。什麼是ThreadPool的安全大小?當我用一些大數字作爲參數創建FixedTheradPool時會發生什麼?

+3

你好邁克爾,一些要點: 你認爲「一大堆電話號碼」? 您的應用會遇到哪些系統規格? 當使用特定批處理線程時,可以使用內存量。堆和處理器速度也考慮到了計算。 此致敬禮, 錦。 – 2009-06-22 18:28:08

+0

除此之外,請閱讀此處的類比:http://java.sun.com/docs/books/tutorial/essential/concurrency/pools.html以查看您的應用程序是否適合FixedThread池的漏洞。 – 2009-06-22 18:30:04

回答

6

如果每個工作線程需要進行Web服務調用,那麼池中的線程數量應該受到Web服務可以處理的同時請求數量的強烈影響。除此之外的任何其他線程都只會使Web服務不堪重負。

+0

http行爲就像他的FixedThreadPool一樣,不需要擔心調用和獲取響應。存在的主要問題是大衆hes處理的大小,記憶效果。堆積和機器的工作速度。 – 2009-06-22 18:40:40

2

我已經讀過某處,線程的最佳數量是核心數* 25。似乎.NET使用此作爲ThreadPool的默認值。但是,如果您有大量Web服務調用,則最好使用單個線程並檢查Web服務調用的列表以獲取響應。當響應到達時,只處理條目並將其從列表中刪除。

+0

它會收集更多的責任,他的程序需要,他需要的是他的流程更多的吞吐量。 – 2009-06-22 18:36:46

+1

http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=588核心* 25號。 – 2009-06-22 18:39:12

2

如果您具有對Web服務的開發訪問權,請考慮創建一個批處理函數以在一次調用中檢查多個電話號碼。

在較新的.NET中,有一個ThreadPool可以根據自己的性能配置文件進行增長和縮小。不幸的是,Java的版本是固定的,或者根據傳入的工作增長到極限。

我們曾經有過類似的擔憂。我們的解決方案是讓客戶可以根據自己的喜好調節游泳池的大小並調整性能。

對於I/O操作池大小可以考慮一些網絡和數據屬性:網絡帶寬,消息大小,Web服務的處理時間和樣式,本地內核數量。

2

如果每個計算等同於對Web服務的調用,那麼您應該考慮您要在該服務上投入多少負載/該服務的所有者將允許或將允許多少個併發連接。大多數可公開訪問的服務一次只能從單個用戶獲得一個這樣的連接。如有可能,請聯繫服務的所有者以瞭解其使用政策。這種連接的數量將決定您可以使用的線程數量。

0

不要忘記,你創建的每個線程也會對內存的堆棧大小提出要求。因此,創建線程池將影響進程的內存佔用量(請注意,某些池在實際需要之前不會創建線程,因此在啓動時不會看到任何內存增加)。

此堆棧大小可通過-Xss(類似於-Xmx等)進行配置。我相信每個線程的默認值是512Kb。目前我無法找到任何權威來證實這一點。

+0

是的,在Linux上,每個線程都有自己的棧,默認大小爲512kB。 – 2009-06-22 18:47:42

0

我不知道你會更好地使用NIO而不是線程,因爲你的限制因素將是Web服務器+網絡瓶頸,而不是客戶端CPU。

否則,最多不應超過Web服務支持的併發連接數。

0

如果你在做平行數組操作的重度計算,那麼經驗法則是讓處理器的數量爲線程數。

1

我們假設Web服務具有無限可擴展性,並且沒有人會關心您是否使用請求發送垃圾郵件。我們還假設Web服務響應在1秒範圍內,而本地處理時間是5毫秒。

當您擁有與處理內核相同數量的繁忙線程時,吞吐量將達到最大。

在這些假設下,您無法在多核處理器上爲任何合理的線程池大小最大化吞吐量。要實現每秒最大事務數,您必須打破每個連接模型的線程數。查找前面提到的非阻塞I/O(NIO)或異步完成令牌模式的Java實現(Windows中的IO完成)。

請注意,爲每個創建的線程保留的堆棧內存實際上僅保留爲地址空間,而不是實際分配或提交的內存。隨着堆棧嘗試增加異常,導致堆棧內存按需提交。其結果是它只與32位內存管理器有關。對於64位內存,即使只使用物理內存回退該空間的一小部分,也可以擁有巨大的地址空間。至少,這是我對Windows工作的理解,我不確定Unix世界。可以考慮

8

東西是看

Runtime.getRuntime().availableProcessors() 

這給多少線程將使意義對於系統的一些方向。