下面是Sam Varshavchik解釋的基本實現。
Live demo
爲什麼我添加了一個local_queue
的原因是爲了確保我們的m_Mutex
解鎖的時候了。如果將其刪除,調用push_task
的線程可能會被阻塞。
析構函數調用stop()
,它設置m_Running
到false
,通知線程關於它,並等待它完成處理所有剩餘的任務。
如果工人階級死亡,線程也死了,這很好。
我的例子只是創建3個線程和每個線程for (int i = 0; i < 5; i++)
5個任務,主要是爲了確保在ideone所有的輸出顯示,但我已經有10個線程和每個線程任務5000測試了它和它運行得很好。
do_work
函數有兩行,如果您希望輸出流正確同步,您可以取消註釋。 該課程有多線程支持。
可以stop()
並重新start()
線程多次,你在線程池實現像
class Worker
{
public:
Worker(bool start) : m_Running(start) { if (start) private_start(); }
Worker() : m_Running(false) { }
~Worker() { stop(); }
template<typename... Args>
void push_task(Args&&... args)
{
{
std::lock_guard<std::mutex> lk(m_Mutex);
m_Queue.push_back(std::bind(std::forward<Args>(args)...));
}
m_Condition.notify_all();
}
void start()
{
{
std::lock_guard<std::mutex> lk(m_Mutex);
if (m_Running == true) return;
m_Running = true;
}
private_start();
}
void stop()
{
{
std::lock_guard<std::mutex> lk(m_Mutex);
if (m_Running == false) return;
m_Running = false;
}
m_Condition.notify_all();
m_Thread.join();
}
private:
void private_start()
{
m_Thread = std::thread([this]
{
for (;;)
{
decltype(m_Queue) local_queue;
{
std::unique_lock<std::mutex> lk(m_Mutex);
m_Condition.wait(lk, [&] { return !m_Queue.empty() + !m_Running; });
if (!m_Running)
{
for (auto& func : m_Queue)
func();
m_Queue.clear();
return;
}
std::swap(m_Queue, local_queue);
}
for (auto& func : local_queue)
func();
}
});
}
private:
std::condition_variable m_Condition;
std::list<std::function<void()>> m_Queue;
std::mutex m_Mutex;
std::thread m_Thread;
bool m_Running = false;
};
void do_work(unsigned id)
{
//static std::mutex cout_mutex;
//std::lock_guard<std::mutex> lk(cout_mutex);
std::cout << id << std::endl;
}
int main()
{
{
Worker workers[3];
int counter = 0;
for (auto& worker : workers)
worker.start();
for (auto& worker : workers)
{
for (int i = 0; i < 5; i++)
worker.push_task(do_work, ++counter + i);
}
}
std::cout << "finish" << std::endl;
getchar();
return 0;
}
來源
2016-03-06 16:44:21
Jts
查找。您將需要更多級別的間接工作負載傳遞。 –
您需要有一種方法將工作傳遞給您的線程(通過隊列或其他方式)。這與你所展示的有很大不同。這對於proactor來說是一個很好的用例,就像boost :: asio一樣 – Chad