简单版 -- 只能取线程执行函数,不能拿到执行结果
转自 https://www.cnblogs.com/guolongzheng/p/13711875.html
thread_pool_manager.h
#pragma once
#include <thread>
#include <vector>
#include <queue>
#include <condition_variable>
#include <mutex>/*
* 抽象一个任务 根据自己的需求扩展
*/
class AbsTask {
public:
AbsTask() = default;
virtual ~AbsTask() = default;
public:
virtual void run() = 0;
};template<typename _Ty>
class ThreadPoolManage {
public:
ThreadPoolManage(unsigned int nMaxThread)
: mMaxThreadNum(nMaxThread), mThreadStatus(false)
{
//启动的时候就要创建线程
auto maxNum = std::thread::hardware_concurrency();
//获取当前操作系统中CPU的核心数量 根据核心数量来设置 最大工作线程的并发数量
mMaxThreadNum = mMaxThreadNum > maxNum ? maxNum : mMaxThreadNum;
//创建工作线程池
for (auto i = 0; i < mMaxThreadNum; i++) {
mWorkers.emplace_back([this] {
while (true) {
std::unique_lock<std::mutex> lock(this->mQueue_mutex);
this->mCondition.wait(lock, [this]() {return this->mThreadStatus || !this->mTasks.empty(); });
// 需要退出线程,并且任务列表为空,说明该退出了
if (this->mThreadStatus && this->mTasks.empty()) {
return;
}//获取队列头部的任务
auto task = std::move(this->mTasks.front());
//任务出队
this->mTasks.pop();
//执行工作
task.run();
}
});
}
}~ThreadPoolManage()
{
{
std::unique_lock<std::mutex> lock(this->mQueue_mutex);
this->mThreadStatus = true;
}//通知所有线程起来工作 然后退出
this->mCondition.notify_all();
//等待所有线程工作完毕
for (std::thread& worker : this->mWorkers) {
if (worker.joinable()) {
worker.join();
}
}
}/*
* 添加任务到任务队列
*/
void addTask(_Ty& task)
{
std::unique_lock<std::mutex> lock(this->mQueue_mutex);
if (mThreadStatus) {
throw std::runtime_error("workers stop");
}
mTasks.emplace(std::move(task));
mCondition.notify_one();
}
private:
std::vector<std::thread> mWorkers; // 工作线程池
std::queue<_Ty> mTasks; // 任务队列
unsigned int mMaxThreadNum; // 工作线程的最大并发数量
std::condition_variable mCondition; // 条件变量 控制线程池中线程的工作状态
std::mutex mQueue_mutex; // 工作线程锁
bool mThreadStatus; // 控制线程的开关, false: 继续工作, true: 退出线程
};
thread_pool_manager.cpp
#include <iostream>
#include <chrono>
#include "thread_pool_manager. h"class Task :public AbsTask {
public:
void run() override
{
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "works ...... " << std::this_thread::get_id() << std::endl;
}
};int main()
{
ThreadPoolManage<Task> ThreadPool(8);
for (size_t i = 0; i < 256; i++) {
Task task;
ThreadPool.addTask(task);
}// 主进程这里直接退出不会有问题,因为退出之前会调ThreadPoolManage的析构,那里面有join
return 0;
}
升级版 -- 可以拿到执行结果
转自 https://blog.csdn.net/kenjianqi1647/article/details/110834293
说明:
1、可以拿到线程执行结果的线程池,肯定会用到模板函数,因为不通的任务的参数个数、参数类型、返回值类型不一样。
2、我们通常的习惯是类的声明(包含成员函数)和定义会分开写在.h文件和.cpp文件里面,此时就会遇到一个问题:编译不过。原因是函数模板声明和定义必须写在一起。
注意:函数模板声明和定义必须写在一起
转自https://blog.csdn.net/Currybeefer/article/details/125705223