1 Star 0 Fork 0

bksczm / Linux

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
pthread_pool.hpp 5.49 KB
一键复制 编辑 原始数据 按行查看 历史
bksczm 提交于 2026-07-26 20:09 +08:00 . 线程池
#pragma once
#include "mutex.hpp"
#include "cond.hpp"
#include "pthread.hpp"
#include "Log.hpp"
#include <vector>
#include <queue>
#include <functional>
#include <utility>
#define default_thread_num 10
namespace bksw
{
template<typename T>
class pthread_pool
{
private:
std::vector<bksw::pthread> _vp; // 工作线程数组,任务类型与队列统一
std::queue<T> _qt; // 任务队列
int _thread_num; // 线程数量(原_capacity重命名)
mutex _mutex; // 保护队列与状态的互斥锁
cond _con; // 条件变量
statue _st; // 线程池状态
// 单例静态成员
static pthread_pool<T>* _sppt;
static mutex _lock;
// 工作线程核心执行函数
void Execute()
{
while (true)
{
// 1. 加锁,所有共享状态的读写都在锁内
_mutex.lock();
// 2. 队列为空 且 线程池运行中 → 等待
// while 循环规避虚假唤醒,同时判断状态保证停止时能退出
while (_qt.empty() && _st == statue::RUNNING)
{
_con.wait(_mutex);
}
// 3. 退出条件:线程池已停止 且 队列为空
if (_st == statue::STOP && _qt.empty())
{
_mutex.unlock();
break;
}
// 4. 取出任务,立即解锁,避免任务执行时长占用锁
T task = std::move(_qt.front());
_qt.pop();
_mutex.unlock();
// 5. 锁外执行任务
task();
}
}
// 单例:构造函数私有化
explicit pthread_pool(int thread_num)
: _thread_num(thread_num)
, _st(statue::NEW)
{
for (int i = 0; i < _thread_num; ++i)
{
// 预先构造线程对象,不启动;不使用detach
bksw::pthread ptd;
_vp.emplace_back(ptd);
LOG(Loglevel::INFO) << "线程池初始化线程 " << i << " 完成";
}
}
public:
// 禁用拷贝与赋值
pthread_pool(const pthread_pool&) = delete;
pthread_pool& operator=(const pthread_pool&) = delete;
// 单例获取接口
static pthread_pool<T>* GetInstance(int thread_num = default_thread_num)
{
// 双重检查锁定(DCL)
if (_sppt == nullptr)
{
guidemutex guard(_lock); // RAII守卫锁,自动加解锁,避免死锁
if (_sppt == nullptr)
{
_sppt = new pthread_pool<T>(thread_num);
_sppt->start();
LOG(Loglevel::INFO) << "线程池单例创建成功";
}
}
return _sppt;
}
// 提交任务(多生产者并发调用安全)
template<typename Func, typename... Args>
bool assign(Func&& func, Args&&... args)
{
_mutex.lock();
// 停止状态下不接受新任务,判断在锁内保证原子性
if (_st != statue::RUNNING)
{
_mutex.unlock();
LOG(Loglevel::DEBUG) << "线程池未运行,任务提交失败";
return false;
}
// 包装任务并入队,使用移动语义减少拷贝
_qt.emplace(std::bind(std::forward<Func>(func), std::forward<Args>(args)...));
_mutex.unlock();
// 只唤醒一个等待线程,避免惊群
_con.signal();
return true;
}
// 启动线程池
void start()
{
_mutex.lock();
if (_st != statue::NEW)
{
_mutex.unlock();
return;
}
_st = statue::RUNNING;
_mutex.unlock();
// 先设状态再启动线程,避免状态不一致
for (auto& th : _vp)
{
th.start(&pthread_pool<T>::Execute, this);
}
LOG(Loglevel::DEBUG) << "线程池启动完成";
}
// 停止线程池(优雅退出:处理完所有已入队任务再停止)
void stop()
{
_mutex.lock();
if (_st != statue::RUNNING)
{
_mutex.unlock();
return;
}
_st = statue::STOP;
_mutex.unlock();
// 唤醒所有等待线程,让它们检查退出状态
_con.broadcast();
LOG(Loglevel::DEBUG) << "线程池已发出停止信号";
}
// 等待所有工作线程退出
void join()
{
for (auto& th : _vp)
{
th.join();
}
LOG(Loglevel::INFO) << "所有工作线程已退出";
}
// 析构函数:自动停止并回收线程
~pthread_pool()
{
if (_st == statue::RUNNING)
{
stop();
join();
}
}
};
// 静态成员类外定义
template<typename T>
pthread_pool<T>* pthread_pool<T>::_sppt = nullptr;
template<typename T>
mutex pthread_pool<T>::_lock;
} // namespace bksw
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/bskczm/linux.git
git@gitee.com:bskczm/linux.git
bskczm
linux
Linux
master

搜索帮助