前言
最近在学习Stanford的CS149课程,这个课程是有关并行计算的,讲了很多很有用的知识,在做编程作业的过程中也遇到了很多困难,看了很多资料,我将它们整理出来,以后看也方便一些。
实现
线程池的具体实现就是将线程提前创建好放入vector等容器中,等到有任务的时候就线程就取出任务执行,没有任务就处于休眠的状态,所以线程池里头的线程的函数就是一个死循环,当我们关闭线程池的时候死循环就会退出。线程池的函数队列实现是最麻烦的,因为要考虑到不同的函数参数和返回值类型,但是参考资料里头的github里面有完整的讲述,作者写的很清楚,我就不赘述了。
具体的实现如下:
#include <thread>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <queue>
#include <future>
class ThreadPool {
public:
explicit ThreadPool(size_t threadNum) : stop_(false) {
for(size_t i = 0; i < threadNum; ++i) {
workers_.emplace_back([this]() {
for(;;) {
std::function<void()> task;
{
std::unique_lock<std::mutex> ul(mtx_);
cv_.wait(ul, [this]() { return stop_ || !tasks_.empty(); });
if(stop_ && tasks_.empty()) { return; }
task = std::move(tasks_.front());
tasks_.pop();
}
task();
}
});
}
}
~ThreadPool() {
{
std::unique_lock<std::mutex> ul(mtx_);
stop_ = true;
}
cv_.notify_all();
for(auto& worker : workers_) {
worker.join();
}
}
template<typename F, typename... Args>
auto submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
auto taskPtr = std::make_shared<std::packaged_task<decltype(f(args...))()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
{
std::unique_lock<std::mutex> ul(mtx_);
if(stop_) { throw std::runtime_error("submit on stopped ThreadPool"); }
tasks_.emplace([taskPtr]() { (*taskPtr)(); });
}
cv_.notify_one();
return taskPtr->get_future();
}
private:
bool stop_;
std::vector<std::thread> workers_;
std::queue<std::function<void()>> tasks_;
std::mutex mtx_;
std::condition_variable cv_;
};
这应该是我见过的C++线程池实现里头最简单的了,虽然还有点问题,但是已经足够应付课程作业了,以后熟练了可以再了解更多线程池的实现。