这是线程池的一个简单(也可能是幼稚的)实现。
我想知道,鉴于下面的方法,是否有一种很好的方法可以主动通知线程池线程退出,而不必mStopped
在每次超时后检查布尔值。
我知道有更好的方法来实现线程池 - 但我仍然有兴趣看看下面的代码是否可以在不从根本上改变它的情况下得到改进。
我很高兴听到一般性建议......不一定要修复下面的代码......问题实际上是关于信号/等待线程,线程池只是为了提供一些上下文。
我使用的是 gcc 4.4.6(所以下面的一些语法有点过时了),并且代码是用g++ --std=c++0x main.cc -pthread
#include <vector>
#include <mutex>
#include <thread>
#include <deque>
#include <condition_variable>
#include <functional>
using namespace std;
struct ThreadPool;
struct Worker {
ThreadPool& mThreadPool;
Worker(ThreadPool& threadPool) : mThreadPool(threadPool) {}
void operator()();
};
struct ThreadPool {
vector<thread> mWorkers;
deque<function<void()>> mTasks;
bool mStopped; // not atomic
mutex mMutex;
condition_variable mCond;
ThreadPool() : mStopped(false) {
for (size_t i = 0; i < 5; i++)
mWorkers.push_back(thread(Worker(*this)));
}
~ThreadPool() { stop(); }
void stop() {
if (!mStopped) {
mStopped = true;
for (auto it = mWorkers.begin(); it != mWorkers.end(); ++it)
if (it->joinable()) it->join();
}
}
bool canBreakFromWait() const { return !mTasks.empty(); }
void enqueue(function<void()> f) {
if (mStopped) return;
unique_lock<mutex> lck(mMutex);
mTasks.push_back(f);
mCond.notify_one();
}
};
void Worker::operator()() {
while (true) {
unique_lock<mutex> lck(mThreadPool.mMutex);
mThreadPool.mCond.wait_for(lck, chrono::seconds(1), bind(&ThreadPool::canBreakFromWait, &mThreadPool));
if (mThreadPool.mStopped) break;
auto task = mThreadPool.mTasks.front();
mThreadPool.mTasks.pop_front();
lck.unlock();
task();
}
}
void doWork(int data) {}
int main() {
ThreadPool threadPool;
for (auto i = 0; i < 50; i++)
threadPool.enqueue(bind(doWork, i));
threadPool.stop();
}