#ifndef THREADPOOL_H #define THREADPOOL_H #include #include #include #include #include #include #include #include // #include "spdlog/spdlog.h" // #include "fmt/std.h" /** * @brief 1、使用map存储工作线程,线程id作为键 * 2、采用可变参数模板函数添加任务到任务队列中 * 3、线程池采用单例模式 * 4、有两种添加工作线程的方式,一种带有返回值,一种不带返回值 * * 使用方式: * 1、非成员函数 * void func(int a, int b) { std::cout << a + b << std::endl; } * CPPTP.add_task(func, 1, 2); * 2、成员函数 * void A::func(int a, int b) { std::cout << a + b << std::endl; } * A a; * CPPTP.add_task(&A::func, &a, 1, 2); * */ #define CPPTP ThreadPool::getInstance() class ThreadPool { private: ThreadPool(); ThreadPool(const ThreadPool &tp) = delete; ThreadPool &operator=(const ThreadPool &tp) = delete; public: static ThreadPool& getInstance() { static ThreadPool tp; return tp; } ~ThreadPool(); /** * @brief 向任务队列添加任务函数 * * @tparam F 函数(指针?) * @tparam Args 参数包 * @param f 万能引用 * @param args 万能引用 */ template void add_task(F &&f, Args &&...args) { /* 将函数参数和函数绑定 */ std::function task = std::bind(std::forward(f), std::forward(args)...); /* 作用域是用于解锁lock */ { std::unique_lock lock(m_mutexTask); m_queue_Tasks.emplace(std::move(task)); /* 入队 */ } /* 唤醒一个线程 */ m_cond_Task.notify_one(); } /* 添加带有返回值的任务函数 * future内部定义了一个类型std::result_of::Type */ template auto add_task_with_ret(F&& f, Args&&... args) -> std::future::type> { /* 将类型去一个别名 */ using resultType = typename std::result_of::type; /* 将传入的函数与参数绑定并包装成一个可调用的指针,使用智能指针管理 */ auto task = std::make_shared>( /* 使用forward完美转发,防止右值变成了左值 */ std::bind(std::forward(f), std::forward(args)...) ); /* 获取future对象,用于获取返回值 */ std::future res = task->get_future(); { std::unique_lock lock(m_mutexTask); /* 使用lamba表达式调用封装的函数 */ m_queue_Tasks.emplace([task](){ (*task)(); }); } /* 解锁条件变量 */ m_cond_Task.notify_one(); /* 返回值,函数调用完成后,可以通过这个返回值获取任务的返回值 */ return res; } /****** 获取当前线程池在运行的线程个数,空闲线程的个数 ******/ int getThreadMaxNum(); /* 获取线程池最大线程的个数 */ void setThreadMaxNum(int num); /* 设置线程池最大线程的个数 */ int getThreadMiniNum(); /* 获取线程池最小线程的个数 */ void setThreadMiniNum(int num); /* 设置线程池最小线程的个数 */ int getThreadIdleNum(); /* 获取线程池空闲线程的个数 */ int getThreadRunNum(); /* 获取线程池正在运行的线程个数 */ int getThreadLiveNum(); /* 获取线程池现存的线程个数 */ int getThreadAddNum(); /* 线程池每次创建线程的个数 */ void setThreadAddNum(int num); /* 设置线程池每次创建线程的个数 */ int getThreadMiniIdle(); /* 线程池最小空闲线程的个数 */ void setThreadMiniIdle(int num); /* 设置线程池最小空闲线程的个数 */ int getThreadMaxIdle(); /* 线程池最大空闲线程的个数 */ void setThreadMaxIdle(int num); /* 设置线程池最大空闲线程的个数 */ private: void worker(); /* 工作线程函数 */ void managerThread(); /* 维护线程池的线程,如提前创建线程,销毁线程 */ void createThread(int num); /* 创建新的线程 */ void clearThread(); /* 清除失效的线程实例 */ private: class OneThread; /* 类声明 */ std::map m_mapThreads;/* 线程数组,维护线程池 */ std::list m_exitThreadID; /* 已经退出任务函数的线程ID */ std::queue> m_queue_Tasks;/* 任务队列,任务函数都是无返回值的函数 */ std::condition_variable m_cond_Task; /* 条件变量,没有任务的时候阻塞住 */ bool m_stop; /* 线程是否停止 */ std::mutex m_mutexExitThreadID; /* 互斥锁,搭配环境变量使用,对已经退出的线程ID上锁 */ std::mutex m_mutexTask; /* 互斥锁,搭配环境变量使用,对任务队列上锁 */ std::thread m_managerThread; /* 管理线程 */ int m_threadMaxNum = 256; /* 默认最大线程数 */ int m_threadMiniNum = 5; /* 默认线程池中最小线程数 */ std::atomic m_threadAddNum; /* 每次需要添加的线程个数 */ std::atomic m_threadMiniIdle; /* 如果空闲线程小于这个数,就添加m_ThreadAddNum个线程 */ std::atomic m_threadMaxIdle; /* 最大空闲的线程个数,超过这个个数一定时间,就会销毁多余的 */ std::atomic m_threadRunNum; /* 正在运行的线程个数 */ std::atomic m_threadLiveNum; /* 现有的线程个数 */ std::atomic m_threadExitNum; /* 需要销毁的线程个数 */ }; #endif /* THREADPOOL_H */