我正在嘗試boost::asio::thread_pool在我的應用程式中創建一個執行緒池。我創建了以下玩具示例,以查看我是否理解它的作業原理,但顯然不是 :)
#include <boost/asio/post.hpp>
#include <boost/asio/thread_pool.hpp>
#include <boost/bind.hpp>
#include <iostream>
boost::asio::thread_pool g_pool(10);
void f(int i) {
std::cout << i << "\n";
}
int main() {
for (size_t i = 0; i != 50; i) {
boost::asio::post(g_pool, boost::bind(f, 10 * i));
g_pool.join();
}
}
程式輸出
0
我對兩件事感到困惑:一,如果我正在等待執行緒完成使用g_pool.join(),為什么我不能在下一次迭代中重用執行緒。即,我希望還會看到10,20,30,...在后續迭代中列印的數字等。
其次,我正在創建一個大小為 10 的執行緒池,為什么我至少沒有看到 10 個輸出呢?我無法理解這一點。
請讓我知道我哪里出錯了,提前謝謝!
uj5u.com熱心網友回復:
您在發布第一個任務后加入池。因此,池在您接受第二個任務之前就停止了。這就解釋了為什么你沒有看到更多。
這修復了:
for (size_t i = 0; i != 50; i) {
post(g_pool, boost::bind(f, 10 * i));
}
g_pool.join();
附錄#1
回應評論。如果您想等待特定任務的結果,請考慮未來:
住在 Coliru
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <future>
boost::asio::thread_pool g_pool(10);
int f(int i) {
std::cout << '(' std::to_string(i) ')';
return i * i;
}
int main() {
std::cout << std::unitbuf;
std::future<int> answer;
for (size_t i = 0; i != 50; i) {
auto task = boost::bind(f, 10 * i);
if (i == 42) {
answer = post(g_pool, std::packaged_task<int()>(task));
} else
{
post(g_pool, task);
}
}
answer.wait(); // optionally make sure it is ready before blocking get()
std::cout << "\n[Answer to #42: " std::to_string(answer.get()) "]\n";
// wait for remaining tasks
g_pool.join();
}
使用一種可能的輸出:
(0)(50)(30)(90)(110)(100)(120)(130)(140)(150)(160)(170)(180)(190)(40)(200)(210)(220)(240)(250)(70)(260)(20)(230)(10)(290)(80)(270)(300)(340)(350)(310)(360)(370)(380)(330)(400)(410)(430)(60)(420)(470)(440)(490)(480)(320)(460)(450)(390)
[Answer to #42: 176400]
(280)
附錄 #2:序列化任務
如果要序列化特定任務,可以使用鏈。例如,根據引數模 3 的其余部分序列化所有請求:
住在 Coliru
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <future>
boost::asio::thread_pool g_pool(10);
int f(int i) {
std::cout << '(' std::to_string(i) ')';
return i * i;
}
int main() {
std::cout << std::unitbuf;
std::array strands{make_strand(g_pool.get_executor()),
make_strand(g_pool.get_executor()),
make_strand(g_pool.get_executor())};
for (size_t i = 0; i != 50; i) {
post(strands.at(i % 3), boost::bind(f, i));
}
g_pool.join();
}
可能的輸出:
(0)(3)(6)(2)(9)(1)(5)(8)(11)(4)(7)(10)(13)(16)(19)(22)(25)(28)(31)(34)(37)(40)(43)(46)(49)(12)(15)(14)(18)(21)(24)(27)(30)(33)(36)(39)(42)(45)(48)(17)(20)(23)(26)(29)(32)(35)(38)(41)(44)(47)
Note that all work is done on any thread, but tasks on a strand happen in the order in which they were posted. So,
- 0, 3, 6, 9, 12...
- 1, 4, 7, 10, 13...
- 2, 5, 8, 11, 14...
happen strictly serially, though
- 4 and 7 don't need to happen on the same physical thread
- 11 might happen before 4, because they're not on the same strand
Even More
In case you need more "barrier-like" synchronization, or what's known as fork-join semantics, see Boost asio thread_pool join does not wait for tasks to be finished (where I posted two answers, one after I discovered the fork-join executor example).
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/359311.html
上一篇:更新執行緒中的索引變數
下一篇:當執行緒不拋出例外時會發生什么?
