2010-07-28 265 views
0

我現在正在爲服務器客戶端應用程序工作(僅用於學習目的),並且正在嘗試獲取有關此應用程序中有關線程的設計決策的信息。多線程vs單線程

目前我有一個線程負責與客戶端的所有非阻塞io。當它接收到任何數據時,它將它發送給一個工作線程,該線程從這些字節中創建一個「指令集」,然後相應地對其執行操作。但是,根據指令集,它可以對任意數量的數百個對象起作用(每個對象將在2到12個可以與之交互的客戶端之間加蓋)。我想知道是否應該處理同一個線程上的所有指令集,並且在處理每個集合時阻塞,或者如果我應該爲每個對象創建單獨的線程,然後將每個接收到的指令集傳遞給給定的對象線程處理。

我的問題歸結爲什麼時候(如果有的話)有更多不活動的線程正在等待數據減慢系統,相比之下,有一個工作線程處理所有數據(以及處理每條指令時的塊組)。

如果我爲每個對象創建了一個單獨的線程,那麼我認爲它可以增加併發性,因爲一旦主工作線程創建了一個指令集,它就可以傳遞它來處理,並且無意地開始處理下一個指令系統。

但是,我一直聽說如何創建和管理線程有一個底層成本,因爲操作系統必須管理它們。因此,如果我爲最多可以有2個客戶端進行交互的對象創建一個線程,管理它的底層成本會否定它的併發利益,只有2個客戶端可以利用該併發?

與往常一樣,任何意見/文章不勝感激:)

回答

3

我建議通過以下的Java EE應用服務器樹立了榜樣。

爲傳入請求和處理程序線程的池設有隊列。當請求進入時,讓控制器從池中取出一個處理程序線程,將請求從隊列中取出,並將其交給處理程序線程處理。線程完成後,將其放回池中。

如果請求數量大於處理程序線程的數量,則隊列允許它們累積並等待線程變爲可用。

這樣的設計給你帶來兩個好處:

  1. 它可以讓你設定的處理線程池的大小和它匹配到你的服務器資源
  2. 當他們超過池容量,因此會扼殺傳入的請求你沒有阻止和等待或失去請求。

併發是你的朋友在這裏。這將有助於保持服務器的可擴展性。

+0

這是一個更優雅的解決方案,然後我就是想象。謝謝:) – vimalloc 2010-07-28 00:31:33

0

如果線程實際上處於睡眠狀態,則開銷成本應該不過是首先啓動它們而花費的成本。沉睡的線程有一個相當有效的方法,直到需要時才能入睡:等待中斷。 (注意一種常見的睡眠方法是在時鐘中斷後喚醒,這就是你如何指定應該睡眠的時間)。如果那些線程沒有利用硬件,因爲它們正在喚醒某些類似定時器的東西,而不是某個更特定於您的程序的東西,那麼開銷可能是天文數字,因爲處理器將強制執行所有上下文開關特別是清空緩存。

+0

雖然睡眠線程的CPU成本不算什麼,但內存開銷可能相當高,如果有大量睡眠線程持續存儲大塊數據,則效果與內存大致相同泄漏。 – 2010-07-28 01:09:28

0

單向測試。有時你必須阻止,除非你確信自己的計算能力,否則你不能只是衝擊一切。機器越慢/功能越差,阻塞越多,就會變得無用。設計你的應用程序以適應這種情況。更好的是讓它跟蹤正在發生的事情並讓它自行調整。