C++如何实现一个线程池?(代码示例)


C++线程池实现包含阻塞任务队列、工作线程组、停止标志、条件变量和互斥锁;支持任意可调用对象入队,返回future获取结果,析构时安全等待并停止所有线程。

用C++实现一个轻量、实用的线程池,核心是管理一组复用的工作线程,配合任务队列和同步机制。下面是一个基于 std::threadstd::queuestd::mutexstd::condition_variable 的简洁实现,支持任意可调用对象(lambda、函数指针、bind等),并具备安全停止功能。

线程池的基本结构设计

一个最小可用线程池需包含:

  • 一个阻塞任务队列(线程安全)
  • 一组运行中的工作线程
  • 控制生命周期的标志(如 m_stop
  • 用于唤醒等待线程的条件变量
  • 保护共享数据的互斥锁

完整可运行代码示例

以下为 C++11 及以上兼容的实现(无需第三方库):

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

class ThreadPool { public: explicit ThreadPool(size_t threads) : m_stop(false) { for (size_t i = 0; i < threads; ++i) { m_workers.emplace_back([this] { while (true) { std::function task; { std::unique_lock lock(m_queue_mutex); m_condition.wait(lock, [this] { return m_stop || !m_tasks.empty(); }); if (m_stop && m_tasks.empty()) return; task = std::move(m_tasks.front()); m_tasks.pop(); } task(); } }); } }

templatezuojiankuohaophpcnclass F, class... Argsyoujiankuohaophpcn
auto enqueue(F&& f, Args&&... args) 
    -youjiankuohaophpcn std::futurezuojiankuohaophpcntypename std::result_ofzuojiankuohaophpcnF(Args...) youjiankuohaophpcn::typeyoujiankuohaophpcn {
    using return_type = typename std::result_ofzuojiankuohaophpcnF(Args...) youjiankuohaophpcn::type;

    auto task = std::make_sharedzuojiankuohaophpcnstd::packaged_taskzuojiankuohaophpcnreturn_type()youjiankuohaophpcnyoujiankuohaophpcn(
        std::bind(std::forwardzuojiankuohaophpcnFyoujiankuohaophpcn(f), std::forwardzuojiankuohaophpcnArgsyoujiankuohaophpcn(args)...)
    );

    std::futurezuojiankuohaophpcnreturn_typeyoujiankuohaophpcn res = task-youjiankuohaophpcnget_future();
    {
        std::unique_lockzuojiankuohaophpcnstd::mutexyoujiankuohaophpcn lock(m_queue_mutex);
        if (m_stop) throw std::runtime_error("enqueue on stopped ThreadPool");
        m_tasks.emplace([task]() { (*task)(); });
    }
    m_condition.notify_one();
    return res;
}

~ThreadPool() {
    {
        std::unique_lockzuojiankuohaophpcnstd::mutexyoujiankuohaophpcn lock(m_queue_mutex);
        m_stop = true;
    }
    m_condition.notify_all();
    for (std::thread &t : m_workers) {
        if (t.joinable()) t.join();
    }
}

private: std::vector<:thread> m_workers; std::queue<:function>> m_tasks; std::mutex m_queue_mutex; std::condition_variable m_condition; bool m_stop; };

如何使用线程池提交任务

支持无返回值和带返回值两种常见场景:

无返回值任务:

ThreadPool pool(4);
pool.enqueue([]{ std::cout << "Hello from thread\n"; });

带返回值任务(自动获取 future):

auto result = pool.enqueue([](int a, int b) { return a + b; }, 10, 20);
std::cout << result.get() << "\n"; // 输出 30

捕获局部变量的 lambda:

int x = 42;
auto fut = pool.enqueue([x]{ return x * 2; });
std::cout << fut.get() << "\n"; // 输出 84

注意事项与改进方向

该实现在教学和中小型项目中足够稳健,但生产环境可考虑:

  • 任务优先级支持(改用优先队列)
  • 空闲线程超时回收(避免常驻过多线程)
  • 任务取消机制(需在 callable 中主动检查中断标记)
  • 更细粒度的异常传播(当前异常会终止 worker 线程)
  • 使用 std::jthread(C++20)简化析构时 join 逻辑

不复杂但容易忽略:确保所有任务对象在线程池销毁前完成,或显式等待 future;避免在任务中持有线程池自身的引用,防止循环依赖和析构死锁。


# ai  # c++  # ios  # stream  # 同步机制  # red  # 局部变量  # bool  # void  # 循环  # Lambda  # 指针  # private  # 线程  # 多线程  # Thread  # function  # 对象  # 返回值  # 死锁  # 是一个  # 互斥  # 两种  # 第三方  # 如何使用  # 复用  # 并具备  # 细粒度 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: 如何在 Go 中调用动态链接库(.so)中的函数  Win11怎么查看硬盘型号_Windows 11检测硬盘信息方法【技巧】  如何在Golang中使用time处理时间_Golang time时间解析与格式化方法  Win11怎么关闭贴靠布局_Win11禁用窗口最大化时的布局菜单  C++中的std::shared_from_this有什么用?C++安全获取this的shared_ptr【智能指针】  如何测试您的网站全球打开速度-网站海外测速工  如何用正则与预处理结合精准拦截拼接式垃圾域名  Win11怎么设置麦克风权限_允许应用访问Win11麦克风【详解】  windows 10专注助手怎么关闭_windows 10禁用通知提醒功能方法  Python装饰器复用技巧_通用能力解析【教程】  MAC怎么截图并快速编辑_MAC自带截图快捷键与标注工具使用【方法】  Win11怎么关闭小组件_Win11禁用任务栏天气与小组件方法【设置】  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  php中self::能调用子类重写的方法吗_静态绑定与重写关系【介绍】  Win11怎么设置虚拟内存_Windows 11优化内存性能提升速度【技巧】  Win11怎么更改盘符_Win11磁盘管理修改驱动器号【步骤】  如何使用Golang recover捕获panic_防止程序崩溃并处理异常  Win11怎么设置任务栏对齐方式_Windows11个性化任务栏行为  Windows10系统怎么查看硬盘健康_Win10 SMART信息检测工具  Golang如何遍历目录文件_Golang filepath.Walk目录遍历操作方法  c++中的std::conjunction和std::disjunction是什么_c++模板元编程逻辑运算【C++17】  Win11文件夹预览图不显示怎么办_Win11缩略图缓存重建修复【教程】  php打包exe如何加密代码_防反编译保护方法【技巧】  如何在Golang中实现基础配置管理功能_Golang配置文件读取与更新示例  Win11怎么自动隐藏任务栏_Win11全屏显示设置【美化】  PHP主流架构怎么处理表单验证_规则与自定义【技巧】  Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  Python网络超时处理_健壮性设计说明【指导】  如何使用Golang配置安全开发环境_防止敏感信息泄露  Win10系统更新错误0x80240034怎么办 Win10更新错误解决法【方法】  Win10怎样卸载iTunes_Win10卸载iTunes步骤【步骤】  如何在Golang中捕获JSON序列化错误_Golangjson.Marshal错误处理示例  php8.4如何配置ssl证书_php8.4https访问配置指南【教程】  c++协程和线程的区别 c++异步编程模型对比【核心】  如何使用Golang读取日志文件_Golang bufio Scanner日志处理示例  如何在Golang中编写端到端测试_Golang E2E测试流程示例  Win11怎么关闭自动修复_跳过Win11开机自动修复循环【技巧】  Win10怎么卸载爱奇艺_Win10彻底卸载爱奇艺方法【步骤】  c++如何打印函数堆栈信息_c++ backtrace函数与符号名解析【方法】  LINUX下如何配置VLAN虚拟局域网_在LINUX交换机与服务器上的实现  如何在 Go 中正确初始化结构体中的 map 字段  c++中如何求一个数的平方根_c++ sqrt函数与牛顿迭代法  Win10系统怎么查看网络连接状态_Windows10网络和共享中心  php订单日志权限怎么设_php订单日志文件权限设置技巧【技巧】  微信JSAPI支付回调PHP怎么接收_处理JSAPI异步通知数据方法【指南】  Windows10如何更改系统字体大小_Win10辅助功能文本缩放设置  如何在Golang中捕获结构体方法错误_Golang方法返回error处理实践  Mac上的iMovie如何剪辑视频?(新手入门教程)  php485读数据时阻塞怎么办_php485非阻塞读取设置技巧【详解】  Avalonia如何实现跨窗口通信 Avalonia窗口间数据传递 

 2026-01-05

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.