ZMQ任务分发设计
经典的线程池
经典的线程池多数是抢占式
在主线程上有个任务池,当有任务进入时,唤醒一个线程进行任务执行,以下是一个简单线程池的代码
//首先是一个线程数据,用来控制线程的
struct threadData {
std::mutex mtx_; //互斥量
std::condition_variable cond_; //条件变量
bool is_shutdown_ = false; //是否关机
std::queue<std::function<void()>> tasks_; //具体执行任务
};
class ThreadPool {
public:
ThreadPool(size_t thread_cnt_):m_data(new threadData){
//创建指定数量的线程
for(size_t _i = 0 ; _i <thread_cnt_;_i++){
std::thread([this](){
//先进行上锁操作
std::unique_lock<std::mutex> _lk(m_data->mtx_);
for(;;){
//判断当前任务池中是否有任务
if(!m_data->tasks_.empty()){
//如果任务队列中有任务,则拿出任务执行
auto _func = std::move(m_data->tasks_.front());
//将取出的任务弹出
m_data->tasks_.pop();
//解锁
_lk.unlock();
//任务执行
_func();
//上锁
_lk.lock();
}else if(m_data->is_shutdown_){
//如果判断到关机信号,则直接退出
break;
}else{
//等待条件变量唤醒
m_data->cond_.wait(_lk);
}
}
}).detach();//从主线程中分离
}
}
template<class TASK>
void execute(TASK&& task_){
//先上锁
std::lock_guard<std::mutex> _lk(m_data->mtx_);
//放入任务
m_data->tasks_.emplace(std::forward<TASK>(task_));
//唤醒一个线程
m_data->cond_.notify_one();
}
~ThreadPool(){
//先上锁
if(m_data){
{
std::lock_guard<std::mutex> _lk(m_data->mtx_);
m_data->is_shutdown_ = true;
}
m_data->cond_.notify_all();
}
}
private:
std::shared_ptr<threadData> m_data;
};
用流程图来描述线程池的任务执行框架,可以明显发现,a,b,c线程可能会对task_pool进行同时访问,这个时候解决办法就是对task_pool进行加锁处理