C++11 下的线程池实现
C++11 下的线程池实现
需求
1、利用c++11 提供的 、<condition_variable> 、 等头文件来实现线程池实现。
2、任务调度要求:①、依据任务的优先级来调度,优先级越低者先被调度;②当优先级一致时,依据任务到来的时间顺序,即先到先服务。
分析
1、线程池的实现,主要思路是:
①、申请若干的线程放入线程容器中,容器选择vector、list … 皆可;
②、在线程创建时,绑定run方法,让每个线程都在跑run;
③、实现一任务池,将每个任务放入任务池中,每个run线程都会在任务池中拿取任务,并执行。
2、线程容器与任务池容器的选择
①、线程容器选择,由于此容器是存放多线程的容器,不涉及到线程安全问题,不涉及线程同步。作者选用STL vector容器。
②、任务池容器选择,依据需求2,需要任务调度能够实现先来先服务,故拟采用队列queue容器来实现。
③、需求2中要求,根据任务优先级的方式来进行任务调度,queue容器只能在尾端入队,头部出队,无法实现依据优先级来进行队列的重排,有以下思路来实现:思路一:实现一链表实现的队列,但在每次插入新任务时,都需要遍历队列,依据优先级进行队列的重排,此方法,时间复杂度大,pass。
思路二:利用最小堆来实现根据依据任务优先级来进行任务重排的需求。最小堆时间复杂度低。
故结合最小堆和队列思路采用C++11中提供的优先级队列(priority_queue)来实现这个需求。
代码实现
/// 线程池的实现 , 实现对任务进行优先级编号,利用优先级队列来选取任务
/// 利用 C++11 特性来实现线程池
#ifndef _THREAD_POOL_H_
#define _THREAD_POOL_H_
#include <thread>
#include <vector> /// 聊下vector 扩容机制
#include <queue>
#include <functional>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <assert.h>
namespace wyz
{
/// 定义一个Task类
struct Task{
bool operator() (const Task& a, const Task& b)
{
return a.m_priority_int > b.m_priority_int;
}
int m_priority_int; ///任务优先级
std::function<void (void)> m_task_fun; ///任务函数
};
class ThreadPool{
public:
ThreadPool(int threads_num = 4) /// 默认为四,此值建议根据cpu核心数目确定
: m_threads_num(threads_num)
, is_stop(false) {
}
~ThreadPool(){
is_stop = true;
m_condition.notify_all(); /// 通知所有线程
for(auto & w : m_work_threads){
w.join(); /// 主线程会等待所有线程全部结束才会结束线程
}
}
/// 创建线程池
void start(){
if(m_threads_num <= 0){
assert(m_threads_num > 0);
}
for(int i = 0 ; i < m_threads_num; ++i){
m_work_threads.emplace_back(std::bind(&ThreadPool::run, this));
}
}
/// 任务队列内插入任务
bool InsertTask(Task task){
tasks_que_mutex.lock();
m_tasks_que.emplace(task);
tasks_que_mutex.unlock();
m_condition.notify_all();
return true;
}
private:
/// 在任务队列中取出优先级高的任务,并运行
void run(){
/// 如果线程池在运行
while(!is_stop){
Task task;
std::unique_lock<std::mutex> lk(tasks_que_mutex);
//最后一个参数是预制条件,调用wait_for的时候,首先就会判断这个条件,
//如果这个条件返回false,那么会继续等待,如果再超时之前,收到了一个notify
//那么他会再次执行这个预制条件来进行判断,超时的时候也还会再此执行这个条件,
//条件成立就不会再进行等待
m_condition.wait_for(lk
,std::chrono::milliseconds(100)
,[this](){return !m_tasks_que.empty();});
if(m_tasks_que.empty()){
continue;
}
else{
task = m_tasks_que.top(); /// 拿到任务
m_tasks_que.pop();
}
if(task.m_task_fun != nullptr){
task.m_task_fun(); /// 执行任务
}
}
}
private:
int m_threads_num; /// 线程数
std::atomic<bool> is_stop; /// 线程池是否运行
std::vector<std::thread> m_work_threads; /// 线程容器
std::priority_queue<Task , std::vector<Task>, Task> m_tasks_que; /// 任务队列(带优先级)
std::mutex tasks_que_mutex; /// 互斥量
std::condition_variable m_condition; /// 条件变量
};
}
#endif