讲师中心 微信公众号
AI工具推荐 视频效率加速

c++ 线程池实现方法 c++如何设计和实现一个线程池

夏晨小哥_3114

夏晨小哥_3114

发布时间:2026-03-27 15:44:43

|

890人浏览过

|

来源于php中文网

原创

应使用线程池而非频繁创建销毁std::thread,因其避免系统调用、栈分配等开销,防止资源耗尽;核心含固定线程、阻塞队列与唤醒机制;需用std::deque+std::shared_ptr管理任务,支持任意可调用对象及返回值;shutdown须先标记停止再等待空队列后退出,析构时join所有线程;栈溢出需显式设置线程栈大小。

c++ 线程池实现方法 c++如何设计和实现一个线程池

为什么别直接手写 std::thread 循环创建销毁

线程创建/销毁开销远大于任务执行本身,尤其在高频短任务场景下,std::thread 每次构造+join()/detach() 会触发系统调用、栈分配、TLS 初始化。实测 10 万次任务,纯 std::thread 方式比线程池慢 3–5 倍,且容易触发 std::system_error: Resource temporarily unavailable(线程数超系统限制)。

真正该复用的是线程实体,不是任务逻辑。线程池本质是「固定数量的长期存活线程 + 阻塞队列 + 任务分发机制」。

  • 核心结构必须包含:std::vector<:thread></:thread> 存活线程、std::queue 或 std::deque 任务队列、std::mutex + std::condition_variable 协作唤醒
  • 避免用 std::queue 存储可移动对象(如 std::function<void></void>),它不支持移动语义优化;改用 std::deque 更安全
  • 不要在构造函数里直接启动所有线程——得等成员变量(尤其是队列和锁)完全初始化后再 std::thread 启动,否则可能访问未定义内存

如何让 submit() 支持任意可调用对象(含返回值)

用户要的不是“只能跑 void()”的玩具池,而是能接 std::async 那种级别的任务:带参数、有返回值、支持 lambda、成员函数指针。

关键在类型擦除 + std::packaged_task 封装:

立即学习“C++免费学习笔记(深入)”;

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • std::packaged_task 把任意签名转成 std::packaged_task<void></void>,同时绑定 std::future 输出通道
  • 提交时用 auto task = std::make_shared<:packaged_task>>()</:packaged_task> 包一层,再塞进队列;线程取出来后调用 (*task)(),自动触发 future 就绪
  • 注意:不能直接存 std::packaged_task 到 std::queue,它不可拷贝;必须用 std::shared_ptr 或 std::unique_ptr 管理所有权
  • 示例片段:
    template<typename F, typename... Args>
    auto submit(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
        using RetType = typename std::result_of<F(Args...)>::type;
        auto task = std::make_shared<std::packaged_task<RetType()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        std::future<RetType> res = task->get_future();
        {
            std::lock_guard<std::mutex> lock(queue_mutex);
            tasks.emplace([task](){ (*task)(); });
        }
        cv.notify_one();
        return res;
    }

线程池 shutdown 的正确顺序和阻塞点

常见错误是调用 shutdown() 后立刻析构,导致正在运行的任务被强制中断,或等待中的线程永远卡在 wait() 里。

必须分两步走:先停止接收新任务(标记 + 通知),再等存量任务完成(但不等新来的)。

  • 加一个 bool stop_requested = false 成员,shutdown() 只设为 true 并广播 cv.notify_all()
  • 每个工作线程循环里检查:if (stop_requested && tasks.empty()) break; —— 注意是「已无任务且已要求停止」才退出,否则继续消费
  • 析构函数里先调 shutdown(),再对每个 std::thread 调用 join();绝不能用 detach(),否则程序退出时线程还在跑,UB(未定义行为)
  • 如果需要强制终止(如超时),得额外设计取消令牌(cancellation_token),C++20 前没有标准方案,别硬靠 std::thread::interrupt()(已被移除)

Linux 下 std::thread 默认栈大小不够怎么办

默认栈通常 2MB(glibc),但递归深或局部变量多的任务(比如解析大 JSON)会触发 std::system_error: Resource deadlock avoided 或直接段错误——这不是死锁,是栈溢出。

解决方法不是加大全局栈,而是在线程创建时显式指定:

  • 用 pthread_attr_t 设置栈尺寸,再传给 std::thread 底层(需封装);更简单的是改用 pthread_create 直接创建,绕过 std::thread 封装
  • 示例(POSIX):
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setstacksize(&attr, 8 * 1024 * 1024); // 8MB
    pthread_t tid;
    pthread_create(&tid, &attr, worker_func, this);
    pthread_attr_destroy(&attr);
  • Windows 下对应 _beginthreadex 的 stack_size 参数;跨平台方案建议用第三方库(如 boost::thread)或自己封装条件编译
  • 注意:栈太大浪费内存,太小崩溃;建议按任务类型分级——IO 线程用默认,计算密集型单独配大栈

线程池最难的从来不是启动多少个线程,而是任务生命周期管理、异常传播路径、以及 shutdown 时谁等谁、等多久——这些细节没压住,跑几天就崩一次。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2115

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3222

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1096

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

3699

2025.09.10

resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.12.20

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

2700

2025.10.15

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

767

2025.10.24

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

636

2023.11.23

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

40

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn