c++11线程池
大佬写的东西,顶礼膜拜,用到了C++11很多的新知识
后面附有我的思考,不保证对,“?”处是我疑惑的地方
ThreadPool.h
//
// Created by zfr on 2020/9/20.
//
#ifndef PRACTICE_THREADPOOL_H
#define PRACTICE_THREADPOOL_H
#include<vector>
#include<queue>
#include<memory>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<functional>
#include<stdexcept>
class ThreadPool{
public:
explicit ThreadPool(size_t);//构造函数,explicit禁止初始化时的参数类型的隐式转换
//变长参数模版
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>;
~ThreadPool();//析构函数
private:
std::vector<std::thread> workers; //工作向量空间
std::queue<std::function<void()> > tasks; //任务队列
std::mutex queue_mutex; //互斥量
std::condition_variable condition; //条件变量
bool stop; //停止标志
};
inline ThreadPool::ThreadPool(size_t threads) :stop (false) {//构造函数,初始化列表初始化stop为false
for(size_t i = 0; i < threads; ++i){
workers.emplace_back([this]{//分清楚emplace与push在vector中的区别,emplace效率更高
for(;;){//相当于while(true)
std::function<void()> task;//声明了一个返回值void,无参的函数task
{
std::unique_lock<std::mutex> lock(this->queue_mutex);
this->condition.wait(lock, [this]{
return this->stop || !this->tasks.empty();});//开始stop为false并且tasks为空,阻塞当前线程
if(this->stop && this->tasks.empty())//stop为真,并且任务队列为空,直接返回
return;
task = std::move(this->tasks.front());//将任务队列最前面的任务移给task,函数绑定?回调函数?函数指针?
this->tasks.pop();//删除任务队列最前面的任务
}
task();//执行
}
});
}
}
//后置返回值 返回了一个异步调用的结果,存储在future中,返回类型为F函数的类型
//变长参数模版
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type> {//后置返回值 返回了一个异步调用的结果,存储在future中,返回类型为F函数的类型
using return_type = typename std::result_of<F(Args...)>::type;//给返回类型取了个新名字
//forword作用是获取参数原有类型,和右值引用有关,获取原始数据
//bind 将后面的变长函数参数和函数f绑定在一起,形成一个新的可调用实体
//新建一个子线程,把这个新的可调用实体交给子线程去执行
//返回的是一个shared_ptr智能指针
auto task = std::make_shared<std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
//将package_task中的future取出来与新的future联系在一起,共享状态值,return_type为返回参数类型
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(queue_mutex);//用unique_lock对mutex进行包装,管理mutex对象
if (stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace([task]() { (*task)(); });//继续将任务加入任务队列;lambda表达式,返回值是一个函数指针???又回调???
}
condition.notify_one();//给wait那边发送消息,此时tasks中已有任务,tasks非空
return res;
}
inline ThreadPool::~ThreadPool(){
{
std::unique_lock<std::mutex> lock(queue_mutex);//用unique_lock包装mutex变量
stop = true;
}
condition.notify_all();//给所有的wait发送通知
for(std::thread &worker: workers)//等待所有的工作子线程结束,注意引用符号,不知道这里能不能用auto?
worker.join();
}
#endif //PRACTICE_THREADPOOL_H
ThreadPool.cpp
#include<iostream>
#include "ThreadPool.h"
int main(){
ThreadPool pool(4);
auto result = pool.enqueue([](int answer) { return answer; }, 42);
std::cout<<result.get()<<std::endl;
}