前言
线程池通过预先创建一定数量的线程并保存在内存中,可以避免频繁地创建和销毁线程,降低线程创建和销毁的开销。
简化任务调度:只需要将任务提交给线程池,而不需要关心线程的创建、管理和销毁等细节。线程池会自动将任务分配给空闲的线程执行。
代码位置:https://gitee.com/zhongshield/thread_pool
调用方式
调用方继承Task基类,重写Run接口,
通过线程池提供的SubmiTask接口提交任务。
通过Result接收线程池的返回值
示例:实现通过线程池计算区间累加和并返回累加和
1 | #include "thread_pool.h" |
执行结果
1 | ubuntu@ubuntu$ g++ -std=c++17 main.cpp thread_pool.cpp -lpthread |
实现
1 | #ifndef THREAD_POOL_H |
1 | #include "thread_pool.h" |
总结
线程池ThreadPool 提供SubmitTask接口用于提交任务。SubmitTask接口内部通过wait_for等待条件变量notFull_条件成立(条件为任务队列不满),等待1s后条件仍然不成立,打印任务提交失败。如果任务队列不满,提交的任务会放到任务队列中。
线程池ThreadPool 预先执行Start接口,Start接口内部会创建线程对象,并绑定线程函数为线程池ThreadPool 的成员函数ThreadFunc。
线程池ThreadPool 的成员函数ThreadFunc内部,会获取锁,通过wait等待条件变量notEmpty_条件成立(条件为任务队列不空),如果不空,从任务队列中取一个任务,在任务执行前释放锁(否则会阻塞其它线程获取锁,失去线程池的意义)。
add:
线程池ThreadPool的SubmitTask接口返回值是Result,通过task指针构造Result对象 Result(task),并在Result构造函数中调用
task_->SetResult(this); 将Result和task联系起来,线程执行完任务,会通过task向Result设置返回值SetValue,SetValue内部会调用信号量的Post()释放锁。
调用方调用result.GetValue()获取返回值,GetValue()内部会调用信号量sem_.Wait(),如果任务还未执行完毕,会阻塞等待SetValue内部会调用信号量的Post()释放锁。
GetValue阻塞等待可能对调用方不友好,可以增加回调函数通知任务已执行完毕。或者在Result中增加标志/函数(用于判断任务是否执行完毕),从而不在GetValue()中进行阻塞等待。