C++11 下的线程池实现

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值