2011-03-30 122 views
1

我想創建一個簡單的線程池(在* nix系統上)來處理異步通信服務器上的輸入。我有一些問題。起初我只想擁有一個固定的線程數,任意說6.線程池實現

我應該如何發送命令到工作線程?

我想用簡單的socket通信的,像這樣的東西

主線程::發[(RECV)插槽(發送)otherSocket]。

然後讓我的線程簡單地阻止接收呼叫,這是非常低效?

有沒有我應該使用的圖書館?有更好的實施方法嗎?

(後來我打算讓線程動態,我想這將是更容易與一組數字開始)

回答

3

首先,你應該認識到,Windows已不只是一個,但內置的線程池API。如果這還不夠,I/O完成端口基本上也是變相的線程池。因此,有可能沒有很多理由寫你自己的線程池。

除非您打算允許您的線程在不同的機器上運行,否則我不會使用套接字進行通信。線程的正常意圖是它們應該將開銷保持在最低限度;插座不適合。如果你跨越了機器邊界,更多的開銷(網絡通信)變得幾乎不可避免,並且在這種情況下,使用套接字而不是其他一些網絡API並沒有太大的區別。另請注意,對於跨機器工作,您通常需要完成更多工作,將數據從一個數據集合到另一個數據,等等。

假設你堅持一臺機器,我會使用某種方式的線程安全隊列,而不是套接字。我發佈了一個previous answer,你可能會覺得有用。這包括一些示例代碼,它創建一個線程池來爲隊列中的任務提供服務。

+0

我的服務器機器將是一臺linux(可能是ubuntu服務器)機器,你知道是否有任何線程池API可用?如果有必要,我可以使用Windows,但由於缺少poll()函數,我寧願遠離... *** 我將它放在一臺機器上。我喜歡你的隊列實現,我會試試看。 *** 感謝您的回覆。 – ultifinitus 2011-03-30 18:39:49

+0

@ultifinitus:這個特定的隊列實現使用Windows函數,所以它在Linux上不起作用。你需要/需要用pthreads等價物(這不完全簡單)替換Windows函數調用。 Boost有一個C++「期貨」實現,您可能會發現它有用(它基本上是一個線程池的高級API)。我不確定,但我似乎回想起最近版本的gcc在標準庫中有一些未來(他們是新的C++ 11標準的一部分)。 – 2011-03-30 18:46:21

+0

我想我的計劃,在這一秒是隻做一個非常簡單的線程池,如果沒有別的,看看我的微薄技能將帶來的性能收益。 ***我會研究期貨***我有Windows和Posix系統中的線程經驗。 ***現在我只是要創建一個經理類,所以當我的服務器收到一條消息時,它可以將它發給經理,他可以將結果分配給我的線程......再次感謝。 – ultifinitus 2011-03-30 18:53:25

2

是否有您應該使用的圖書館?嗯,當然,否則你不會在標準C++中完成任何你想要的。這帶來了你想使用的平臺......你使用的是Windows還是Linux的某種風格?如果您使用Windows,則可以使用Windows線程和Win Socks 2.如果Linux可以嘗試使用Posix線程,並且至於網絡,我不確定。但是,您可以使用Boost庫來完成所有這些工作,它可以在Windows和Linux操作系統上運行。

就發送消息而言,您可以爲您的消息隊列使用互斥鎖,並且只是簡單地使用一個接收消息函數來鎖定它並添加消息,該消息適用於來自套接字的任何線程,併爲其他線程想要發送消息到該線程。另外不要忘記,當線程正在處理消息時,您還需要鎖定互斥鎖;無論何時訪問該消息隊列,都需要將其鎖定以防止碰撞/數據錯誤。

+0

它可能會在posix兼容系統上運行。對不起,沒有說明這一點,我會繼續編輯。 – ultifinitus 2011-03-30 18:50:29

2

由於您正在使用套接字,您將不得不使用類似select或poll的內容來等待套接字活動。所以對於線程間通信(itc)來說,使用文件描述符的東西將非常有用。這可能是一對或管道或unix域套接字。

然後,您將有一個主線程接受一個新的連接並使用您的itc機制將新的文件描述符傳遞給工作線程。工作線程然後將新的文件描述符添加到選擇/輪詢循環。

如果您正在連接並等待後端服務器(如數據庫),您可能會決定在等待recv完成時阻止,儘管您應該避免這種情況。如果您使用狀態機並將您的堆棧回滾到選擇外觀(在將後端文件描述符添加到選擇/輪詢循環後),則服務器將更具響應性。這將使您的主線程更容易控制您的工作線程。如果你很聰明,你的線程一次可以處理多個請求,並且只有少數線程你應該有一個非常可擴展的服務器。

儘量避免爲itc使用信號量或互斥量,而是通過您的itc管道或unix域套接字發送所有請求。你會爲自己節省很多心理痛苦的競賽條件。

+0

我在系統上使用輪詢來接收主線程上的輸入,並且我正在考慮簡單地等待輪詢,然後在特定線程中拋出文件描述符。我希望我的服務器在任何時候處理1000個以上的客戶端,你知道這個系統的可擴展性嗎? – ultifinitus 2011-03-30 19:54:48

+0

然後我會盡量避免每個會話使用一個線程,而是每個線程有多個會話。訣竅是確保線程只在poll上阻塞。之後多線程的原因就變成了確保所有CPU內核始終被佔用。如果系統中仍然沒有足夠的果汁,那麼您可能需要考慮使用多臺服務器進行某種負載平衡。 – doron 2011-03-30 21:06:03