2012-07-28 172 views
7

我正處於一個問題中,我無法決定採取哪種解決方案。線程池vs許多單線程

這個問題有點獨特。讓我們這樣說,我從網絡上不斷接收數據(每秒2到4次)。現在每個數據都屬於不同的組,比如說。 現在,我們稱這些組,group1,group2等。

每個組都有一個專門的作業隊列,來自網絡的數據將被過濾並添加到其相應的組中進行處理。

起初,我爲每個組創建了一個專用線程,它將從作業隊列獲取數據,對其進行處理,然後進入阻塞狀態(使用鏈接阻塞隊列)。

但是我的高級建議我應該使用線程池,因爲這種方式線程不會被阻塞,並且可以被其他組用於處理。

但是,事情就是這樣,數據即時獲取速度足夠快,並且線程處理它的時間足以讓線程可能不會進入阻塞模式。這也將保證數據按順序進行處理(作業1在作業2之前完成),這在池中很少有機會可能不會發生。

我的老人也傾向於這樣的事實,因爲線程是POOLED(即時通訊認爲他真的是這個詞;)),彙集也將節省我們大量的內存。雖然我不同意這一點,因爲我個人認爲,彙集或不是每個線程都有自己的堆棧內存。除非線程池中有某些我不知道的東西。

最後一件事,我一直認爲集合有助於短時間內在大量工作中出現工作。這是有道理的,因爲線程產生將是一個性能殺手,因爲初始化一個線程所花費的時間比做這項工作花費的時間多得多。所以在這裏彙集有很多幫助。

但在我的情況下,group1,group2,...,groupN總是保持活着。所以如果有數據,他們仍然會在那裏。所以線程產卵在這裏不是問題。

我的老人不服氣,希望我使用pooling解決方案,因爲它的內存佔用很大。

那麼,採取哪條路?

謝謝。

+0

在這樣的情況下,只有一個答案。冷酷的事實!通過適當的受控模型/原型證明哪個更好。您可能會感到驚訝,因爲在不同的情況下,每個人都可能有效。 – 2012-07-28 11:59:18

+0

需要CYA備忘錄 - 通過電子郵件詳細說明您的問題/疑慮,然後按照老年人的建議使用合併解決方案。如果集中設計存在問題,則屏蔽:)。看看你的需求,我可能會用一組專用的線程 - 這些線程只在啓動時創建,並且一個線程比一個異步的狀態引擎更容易調試,而這個狀態引擎必須在需要做的事情時不斷髮布到池中。如果線程池沒有使用異步方法,則任何阻塞調用都會阻塞池線程,從而迫使系統創建更多線程:( – 2012-07-28 12:42:25

+0

如果您的應用程序爲每個組創建一個線程,並且每個線程從自己的隊列中獲取數據,並且無限地運行,你實際上擁有一個固定的線程池,創建一個具有相同線程數量的「真實」線程池不會有太大的改變,使用「真實」線程池可以獲得的好處是隻需少量線程從所有隊列中選擇數據,並且如果線程池隊列中等待的任務太多,或者線程太多,空閒線程池可能會根據需要增長和縮小。 – 2012-07-28 13:24:53

回答

2

好問題。如您所說,共享池確實可以節省您的初始化時間。但它有另一個方面:資源管理。在這裏,我問你這個 - 你有多少組(專用線程)? 它們是否在應用程序的執行期間動態增長?

例如,考慮這個問題的答案是肯定的情況。動態添加新的組類型。在這種情況下,您可能不希望爲每個線程分配一個線程,因爲技術上對將要創建的組的數量沒有限制,您將創建大量線程,並且系統將進行上下文切換而不是實際工作。 線程到救援線程池允許您指定對最大線程數的限制,該線程數可能是可能是創建的,不考慮負載。因此,應用程序可能會拒絕來自某些請求的服務,但是那些能夠正確處理的請求不會嚴重耗盡系統資源。

考慮到上述情況,我很可能在您的情況下,爲每個組設置專用的 線程是非常可行的!

對於老人的信念,它會節省內存也是一樣。事實上,一個線程在堆上佔用內存,但是它真的非常多,如果它是預定義的數量,比如說5。可能是好的。無論如何,除非你是優先考慮的,並且絕對相信你確實有問題,否則你不應該使用集合。

池是一個設計決定,而不是建築設計。您無法在開始時集中注意力,並在遇到後遇到性能問題時,繼續進行優化,以便在發現合併帶來收益時

考慮到請求的序列化(按順序執行),不管你使用的是線程池還是專用線程。順序執行是與單個處理程序線程耦合的隊列的屬性。

+0

感謝您的答覆。至於動態組創建,不會動態創建組。但是有很多團體,大約15-20。預計它們會增加,但它們將在開始時被創建和設置。現在執行順序是一個問題,在這種情況下,合併可能很難實現。但你沒有清楚地告訴我,池中的線程比沒有池的線程需要的內存少。謝謝。 – 2012-07-28 12:25:54

+1

池中的線程與其他線程完全相同。他們消耗相同數量的內存。使用池的好處是它可以避免不斷創建和刪除線程,並且可以將併發線程的數量保持爲固定的或合理的數量。 – 2012-07-28 13:41:08

+2

正如@JBNizet所說,線程池中的線程是相同的線程。只有另一種機制負責他們的一生。線程池中的線程*不會佔用比常規線程少的內存。 請考慮以下內容: 由於您擁有的團隊相對較多,因此我可以謹慎地斷定您可能會更適合使用線程池:正如我之前所提到的,從資源管理的角度來看,如果您擁有比核心更多的線程來運行它們(並且你的邏輯主要是CPU綁定的),你將花費很多時間在ctx切換。再一次,需要徹底的性能測試! – Vitaliy 2012-07-28 17:01:04

3

創建線程將消耗資源,包括每個線程的默認堆棧(IIR 512Kb,但可配置)。因此,合併的好處是您會受到有限的資源衝擊。當然,您需要根據您必須執行的工作來調整游泳池的大小。

對於您的特定問題,我認爲關鍵是在每種情況下實際衡量性能/線程使用情況等。除非遇到約束,否則我可能不會擔心任何其他方式,除非確保您可以將一個實現替換爲另一個實現,而不會對應用程序產生重大影響。請記住,不成熟的優化是所有邪惡的根源Note that

「過早優化」是用來描述一種情況 其中一個程序員可以讓性能因素影響的一段代碼的設計 的短語。這可能導致設計不像原來那樣清潔 或代碼不正確,因爲代碼是 因優化而變得複雜,程序員被 優化分心。

+0

因此,池中的線程使用的內存少於單個內存,這是正確的嗎?另外,pooling實現導致了另一個問題,即序列跳過,以前啓動的線程有時會花費更多的時間,導致另一個線程在稍後開始完成。周圍有什麼? – 2012-07-28 12:11:52

+0

序列號和一個'resequencer'類/線程,用於保存無序輸出的列表/隊列,直到所有更早的進來。 – 2012-07-28 12:48:19