C++线程池学习 Day04

基于前三天的深入分析,第四天的目标是:自己复现整个线程池项目。

首先,我们在Ubuntu虚拟机中创建一个MyThreadPool文件夹:

输入code .

就可以使用vscode打开这个文件夹了

包含了必要的头文件后,我们先声明ThreadPool类

线程池就如同一个流水线工厂,工厂里要有执行任务的工人(线程vector)、任务传送带(任务队列)、提交任务的送货员(enqueue函数)、上下班信号(stop)、中途休息信号(条件变量)。分析完后,我们明确了ThreadPool类的内容。

接着是构造函数与析构函数。在创建工厂后,我们需要立刻招聘工人,所以我们在构造函数中创建好线程,具体多少个由用户自己定义,所以要传一个参数,用来表示创建的线程数量。析构函数发送下班信号,通知左右线程,并等待所有线程做完手头的工作,因此不需要任何参数。

接下来到enqueue函数。用户通过它提交任务(函数),用户具体提交什么函数、它的参数是什么有多少,这个需要等用户具体提交任务的时候才知道。因此,我们不能把这个enqueue函数的参数写死了,使用模板即可解决这个问题。

enqueue函数返回什么?在enqueue中我们提交了任务,提醒任意一个工人来执行任务,然后enqueue函数就结束了。这个时候工人可能还没有执行完任务,所以,这个任务的生命周期必须要超过enqueue函数的生命周期。因此,我们在堆上开辟空间给这个任务,然后用指针管理这片内存。具体是什么指针,后续再说。为了统一,任务队列中的元素都是返回值为void()的无参可调用对象。如何拿到任务执行完的结果?所以,我们希望使用std::future,因此我们可以配合std::packaged_task使用,因为它提供了get_future()接口。这样一来,我们将任务打包,在堆上开辟内存给这个std::packaged_task对象,用指针ptr去管理它,后续这个任务执行完毕后,我们可以通过ptr->get_future()获取和这个std::packaged有共享资源的std::future,这样就可以获取到结果了。

因此,enqueue函数应该返回一个std::future,这个std::future是什么类型的?这个类型就是用户提交的函数返回的类型,具体是什么需要等到用户提交了才知道,但没关系,我们使用了模板。用户提交的函数返回的类型就是std::invoke_result_t<F,Args...>,不需要加typename,因为这本身就是一个类型。为了方便,我们给它起一个别名return_type。所以enqueue函数返回的就是std::future<return_type>对象。但由于这个return_type是编译期才确定的,所以enqueue函数的返回值,我们用auto处理即可。

❓追问:为什么函数f也要完美转发?

答:函数也有左右值之分。

// 1. 函数指针(左值)
void func() {}
enqueue(func);            // 左值
​
// 2. Lambda表达式(左值或右值)
auto lambda = []{};
enqueue(lambda);          // 左值
enqueue([]{ return 42; }); // 右值
​
// 3
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值