基于可变参模板的线程池

threadpool.hpp

cpp 复制代码
#ifndef THREADPOOL_HPP
#define THREADPOOL_HPP

#include <iostream>
#include <thread>
#include <unordered_map>
#include <queue>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>

const int MAX_TASK_COUNT =100;  //默认最大任务数量
const int IDLE_THREAD_MAX_TIME = 60;    //最大空闲时间,单位s

//////////////////////PoolMode////////////////////////
enum class PoolMode
{
    MODE_FIXED,     //固定模式
    MODE_DYNAMIC    //动态模式
};


///////////////////////////////////////////////////////
///////////////////////Thread//////////////////////////
class Thread
{
public:
    using threadFunctionType = std::function<void(int)>;
    //构造函数
    Thread(threadFunctionType func)
        :threadId_(generateThreadId_++)
        ,func_(func)
    {}

    //析构函数
    ~Thread()=default;

    //获得threadId_的值
    int getThreadId() const
    {
        return threadId_;
    }
    //开启线程
    void start()
    {
        std::thread t(func_,threadId_);
        t.detach();
    }
private:
    int threadId_;   //线程Id,对应在线程池容器中的Id
    static int generateThreadId_;    //生成线程I
    threadFunctionType func_;
};
//类外初始化生成线程Id
int Thread::generateThreadId_ = 0; 


///////////////////////////////////////////////////////
/////////////////////ThreadPool///////////////////////
class ThreadPool
{
public:
    //构造函数
    ThreadPool()
        :poolMode_(PoolMode::MODE_FIXED)
        ,initThreadCount_(0)
        //,currentThreadCount_(0)
        ,idleThreadCount_(0)
        ,taskCount_(0)
        ,taskCountMaxThreshold_(MAX_TASK_COUNT)
        ,isRunning_(false)    
    {}

    //析构函数
    ~ThreadPool()
    {
        isRunning_ = false;
        //获取任务队列锁
        std::unique_lock<std::mutex> lock(taskMutex_);
        //唤醒阻塞的线程
        notEmpty_.notify_all();
        //等待所有的线程回收
        exitCond_.wait(lock,[&]()->bool{return threads_.size() == 0;});
    }

    //设置线程池模式,设置成功返回true
    bool setMode(PoolMode poolMode)
    {
        if(isRunning_)
            return false;
        poolMode_=poolMode;
        return true;
    }

    //添加任务
    //返回值类型是future类,future封装的类型是:decltype后func()的返回值类型
    template<typename Func,typename... Args>
    auto addTask(Func&& func,Args&&... args) ->std::future<decltype(func(args...))>
    {
        using RType = decltype(func(args...));
        auto taskPtr = std::make_shared<std::packaged_task<RType()>>(
            std::bind(std::forward<Func>(func), std::forward<Args>(args)...));
        std::future<RType> result = taskPtr->get_future();


        //获取锁
        std::unique_lock<std::mutex> lock(taskMutex_);

        //判断任务队列是否为满
        //wait_for:
        //taskCount < taskCountMaxThreshold_ 为不满足条件 阻塞等待
        //被唤醒后,条件满足则返回true,否则继续阻塞;
        //超时且条件不满足则返回false
        if( !notFull_.wait_for(lock,std::chrono::seconds(1),
            [&]()->bool{return taskCount_ < taskCountMaxThreshold_;}) )
        {
            //超时且条件不满足
            auto task = std::make_shared<std::packaged_task<RType()>> (
                []()->RType{return RType();});
            //先对智能指针解引用获取packaged_task对象,再调用其operator()
            (*task)();
            std::cout<<"failed to add Task!"<<std::endl;
            return task->get_future();       
        }

        //加入任务队列
        taskQueue_.emplace([taskPtr](){
            //当执行taskQueue_中的元素:lambda表达式的时候,将执行以下语句
            (*taskPtr)();
        });
        taskCount_++;
        std::cout<<"add Task succeed!"<<std::endl;

        //通知任务队列不为空
        notEmpty_.notify_all();

        //MODE_DYNAMIC模式,根据任务数量和空闲线程数量、当前线程数量 创建线程
        if(poolMode_ == PoolMode::MODE_DYNAMIC && taskCount_ > idleThreadCount_ 
            && threads_.size() < taskCountMaxThreshold_)
        {
            auto threadFunc = std::bind(&ThreadPool::threadFunction, this,std::placeholders::_1);
            auto threadPtr = std::make_unique<Thread> (threadFunc);
            int threadId = threadPtr->getThreadId();
            threads_.emplace(threadId,std::move(threadPtr));
            threads_[threadId]->start();
            //更新相关计数
            idleThreadCount_++;  
            std::cout<<"thread start:"<<threadId<<std::endl;
        }

        return result;
    }
    

    //线程函数,Thread开始运行后执行的函数
    void threadFunction(int threadId)
    {            
        auto lastTime = std::chrono::high_resolution_clock().now();
        for(;;)
        {
            Task task;
            {
                //获取任务队列锁
                std::unique_lock<std::mutex> lock(taskMutex_);
                //任务数量为0
                while(taskCount_ == 0)
                {
                    if(!isRunning_)
                    {
                        //线程池不是运行状态,回收线程资源
                        threads_.erase(threadId);
                        //更新相关计数
                        idleThreadCount_--;
                        //唤醒退出线程池
                        exitCond_.notify_all();

                        std::cout<<"task is exit"<<std::endl;
                        //结束函数,结束线程
                        return;
                    }

                    //MODE_DYNAMIC模式,当前线程数量大于initThreadCount_,删除空闲一定时间的线程
                    if(poolMode_ == PoolMode::MODE_DYNAMIC)
                    {
                        //每隔一秒轮询:空闲时间是否超过最大限制时间
                        if(std::cv_status::timeout == notEmpty_.wait_for(lock,std::chrono::seconds(1)))
                        {
                            auto now = std::chrono::high_resolution_clock().now();
                            auto dur = now -lastTime;
                            if(dur.count() > IDLE_THREAD_MAX_TIME && threads_.size() > initThreadCount_)
                            {
                                //空闲时间超过一定时间回收线程
                                threads_.erase(threadId);
                                //更新计数
                                idleThreadCount_--;
                                //结束函数,当前线程就结束了
                                std::cout<<"task is exit"<<std::endl;
                                return ;
                            }
                        }
                    }
                    //MODE_FIXED模式,任务为空阻塞线程直到被唤醒
                    else
                    {
                        notEmpty_.wait(lock);
                    }
                }

                //taskCount_ != 0的情况
                //取出任务
                task = taskQueue_.front();
                taskQueue_.pop();
                //更新相关计数
                taskCount_--;
                idleThreadCount_--;
                
                //通知任务数量不为满
                notFull_.notify_all();

                //如果还有任务通知其他线程
                if(taskCount_ > 0)
                {
                    notEmpty_.notify_all();
                }

            }//离开作用域释放锁

            //执行任务
            if(task != nullptr)
            {
            task();
            std::cout<<"finish task"<<std::endl;
            //更新计数
            idleThreadCount_++;
            //执行完任务更新时间
            lastTime = std::chrono::high_resolution_clock().now();
            }

        }

    }

    //开始线程池,初始线程数量默认为计算机核心数量
    void start(int threadCount = std::thread::hardware_concurrency())
    {
        //更新运行状态
        isRunning_ = true;

        //更新相关计数
        initThreadCount_ = threadCount;
        //currentThreadCount_ = threadCount;

        //创建线程类
        for(int i = 0; i < initThreadCount_; i++)
        {
            //绑定线程函数
            auto func = std::bind(&ThreadPool::threadFunction,this,std::placeholders::_1);
            auto threadPtr = std::make_unique<Thread> (func);
            int threadId = threadPtr->getThreadId();
            threads_.emplace(threadId,std::move(threadPtr));
        }

        //启动线程
        for(int i =0; i<initThreadCount_; i++)
        {
            threads_[i]->start();
            idleThreadCount_++;
            std::cout<<"thread start:"<<i<<std::endl;
        }
    }


    //删除拷贝构造和拷贝赋值
    ThreadPool (const ThreadPool& ) = delete;
    ThreadPool& operator=(const ThreadPool& ) = delete;

private:
    
    PoolMode poolMode_;  //线程池模式

    std::unordered_map<int, std::unique_ptr<Thread> > threads_;   //线程容器
    int initThreadCount_;   //初始线程数量
    //std::atomic_int currentThreadCount_;    //当前线程数量
    std::atomic_int idleThreadCount_;   //空闲线程数量

    using Task = std::function<void()>;
    std::queue<Task> taskQueue_;
    //std::queue< std::packaged_task<void()> > taskQueue_;    //任务队列
    std::atomic_int taskCount_;     //任务数量
    int taskCountMaxThreshold_;     //任务数量最大阈值

    std::mutex taskMutex_;              //访问任务队列的锁
    std::condition_variable notEmpty_;    //任务为空条件变量
    std::condition_variable notFull_;     //任务为满条件变量
    std::condition_variable exitCond_;    //退出线程池条件变量
    std::atomic_bool isRunning_; //线程池运行状态,true正在运行

};

#endif

testForThreadPool.cpp

cpp 复制代码
#include "threadpool.hpp"
#include <iostream>

int sum1 (int num1, int num2, int num3)
{
    return (num1+num2+num3);
}
int sum2 (int num1, int num2)
{
    return (num1+num2);
}
int main()
{

    {
        ThreadPool pool;
        pool.start();
        auto futl1 = pool.addTask(sum1,1,2,3);
        auto futl2 =pool.addTask(sum2,1,2);
        std::cout<<"sum1:"<<futl1.get()<<std::endl;
        std::cout<<"sum2:"<<futl2.get()<<std::endl;
    }
    std::cout<<"main out"<<std::endl;
    return 0;
}
相关推荐
令狐少侠20113 小时前
centos7安装MySQL8.4手册
linux·mysql
程序员JerrySUN4 小时前
深度理解 KVM:Linux 内核系统学习的重要角度
java·linux·学习
默|笙4 小时前
【c++】STL-容器 list 的实现
c++·windows·list
屁股割了还要学5 小时前
【C语言进阶】题目练习(2)
c语言·开发语言·c++·学习·算法·青少年编程
大母猴啃编程5 小时前
Linux权限
linux·运维·服务器
麟城Lincoln5 小时前
【Linux-云原生-笔记】LVS(Linux virual server)相关
linux·笔记·云原生·lvs·nat·dr·ipvsadm
菜菜why6 小时前
linux制作镜像、压缩镜像、烧录的方法
linux·镜像·香橙派
Mr_Xuhhh6 小时前
Qt窗口(2)-工具栏
java·c语言·开发语言·数据库·c++·qt·算法
kyle~7 小时前
C++---cout、cerr、clog
开发语言·c++·算法