2013-01-21 97 views
1

我有一個充當服務器的類對象。它從任何地方接收請求,並在請求隊列中推送請求(Producer)。現在有一個消費者線程正在運行,它將從請求隊列中彈出請求,並根據請求調用相應的類方法來提供請求。現在,正在以同步方式執行來自隊列的請求消耗和啓動適當的功能。我想要的是消費者線程彈出隊列中的請求並以異步方式啓動適當的功能,以便消費者可以立即彈出隊列中的下一個請求。C++中的異步函數

我嘗試過的一個解決方案是消費者從隊列中彈出一個請求並創建一個boost::thread並在新線程中啓動相應的功能。我已經保存了std::vector中的線程指針以及boost::thread_group。到現在爲止還挺好。但是這個解決方案存在問題。

一旦我提供了超過150個請求,就有更多的150個線程,之後pthread不會創建新的線程給出錯誤"pthread_create: Resource temporarily unavailable",我相信這意味着當前進程的堆棧已用完,因此無法創建新線程。

問題#1我的請求處理程序不包含while (1),而那些只是在做一些工作和退出,而不是等待任何東西,這就是爲什麼我期待我的初始線程已經完成了他們的處理和退出線程處理函數。考慮到這個問題,如果線程已經完成了處理並退出了,它不應該從堆棧中清理它的東西嗎?

這個問題的一個解決方案是我可以設置線程的堆棧大小,但是在說出1000個線程後仍然會引發此錯誤。

所以我的要求是我必須在一段時間後清理完成的線程(也就是說,當線程指針向量超過100或每隔1分鐘之後)。

問題#2除了像我上面提到的那樣啓動新線程,我應該嘗試使用其他異步函數調用機制。是boost::function + boost::bind異步?這是我提到的情況的一個很好的解決方案嗎?假設我的系統應該每天24小時在線,並且每天都收到> 1000的請求。


更新#1 所以我在我的設計中發現一個問題。我在我的問題#1中提到我的請求處理程序只包含我發現的普通調用不是真的。它從服務器同步下載文件,這本質上是一個阻塞操作。我應該異步下載文件。

如果請求處理程序沒有執行任何阻止操作,則沒有任何方法可以使您的基礎系統無法併發處理線程。

所以,Alex提到有多個消費者線程(我認爲5個就足夠了)從隊列中彈出一個請求,並有一個異步文件下載將解決我的問題。

+0

注意:創建比機器上的處理器更多的線程沒有多大意義。用N個線程創建一個線程池(其中N是您擁有的處理器數量)。讓線程池中的線程從隊列中彈出項目。由於套接字通信的阻塞性質,這是不夠的。您還需要查看異步IO,以便在進行時鐘調用時可以重用該線程。 –

回答

1

一個解決方案是有多個使用者線程,每個使用者線程將工作項目從隊列中彈出並同步處理。它使您能夠管理併發性(避免超額訂閱),同時仍然處理多個項目。您還可以刪除在每個項目上啓動新線程的開銷,我預測這會成爲您的瓶頸之一。

你應該確保你的隊列是爲多個消費者設計的。

從未使用過this implementation,但是一個線程池可能會有所幫助。

+0

還有一個boost :: threadpool –

+0

@LokiAstari建議編輯一個鏈接; 4個小時前Google無法找到它。下班後我會再看。 –

+0

似乎我過時了:http://lists.boost.org/Archives/boost/2009/06/152125.php aparently提升線程池已被替換。 –

1

您已經使用Boost和您下載文件。因此,使用Boost.Asio進行網絡連接以及所有其他多線程/異步相關的東西(如中央調度程序)是非常自然的。

首先,我建議創建一個線程池並在其上運行Asio調度程序:like here。使用Asio異步網絡下載文件:example here。當一個文件被下載時只處理它。

這種方法具有很好的可擴展性,您不必擔心異步網絡或多線程同步(相當棘手的問題)。 Boost.Asio提供了很好的例子來說明如何實現這一點。