下面是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