c++如何实现线程池 c++高并发编程实践【实例】


C++轻量线程池基于std::thread、std::queue、std::mutex和std::condition_variable实现,支持任务提交、原子状态控制与优雅关闭,核心包含线程安全队列、工作线程循环、条件变量等待及析构自动清理。

用 C++ 实现一个轻量、实用的线程池,核心是管理一组复用的线程来异步执行任务,避免频繁创建/销毁线程的开销。下面是一个基于 std::threadstd::queuestd::mutexstd::condition_variable 的简洁实现,支持任务提交、自动扩容(可选)、优雅关闭,已在 C++11 及以上环境验证可用。

线程池基础结构设计

线程池需包含:任务队列(线程安全)、工作线程集合、同步原语(互斥锁 + 条件变量)、运行状态控制。所有任务封装为 std::function,支持 lambda、函数指针、绑定对象等。

关键点:

  • 任务队列用 std::queue + std::mutex 保护,避免多线程竞争
  • std::condition_variable 让空闲线程等待新任务,而非忙等
  • 设置 m_stop 原子标志位,控制线程退出循环
  • 析构时调用 stop(),等待所有线程完成当前任务后退出

完整可运行代码示例

以下是一个最小可行线程池(无任务优先级、无动态扩缩容,但稳定高效):

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

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

class ThreadPool {
public:
    explicit ThreadPool(size_t threads = std::thread::hardware_concurrency())
        : 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.load() || !m_tasks.empty(); });
                        if (m_stop.load() && m_tasks.empty()) return;
                        task = std::move(m_tasks.front());
                        m_tasks.pop();
                    }
                    task();
                }
            });
        }
    }

    template
    auto enqueue(F&& f, Args&&... args)
        -> std::future::type> {
        using return_type = typename std::result_of::type;

        auto task = std::make_shared>(
            std::bind(std::forward(f), std::forward(args)...)
        );

        std::future res = task->get_future();
        {
            std::unique_lock lock(m_queue_mutex);
            if (m_stop.load()) {
                throw std::runtime_error("enqueue on stopped ThreadPool");
            }
            m_tasks.emplace([task]() { (*task)(); });
        }
        m_condition.notify_one();
        return res;
    }

    ~ThreadPool() {
        stop();
    }

private:
    void stop() {
        {
            std::unique_lock lock(m_queue_mutex);
            m_stop = true;
        }
        m_condition.notify_all();
        for (std::thread &t : m_workers) {
            if (t.joinable()) t.join();
        }
    }

    std::vector m_workers;
    std::queue> m_tasks;
    std::mutex m_queue_mutex;
    std::condition_variable m_condition;
    std::atomic m_stop;
};

高并发使用技巧与注意事项

在真实项目中提升线程池稳定性与性能,注意以下实践:

  • 避免任务阻塞过久:单个任务若长时间 I/O 或 sleep,会占用线程资源;可拆分为异步 I/O + 回调,或单独配 I/O 线程池
  • 限制队列长度:无界队列可能 OOM,建议添加 if (m_tasks.size() > MAX_QUEUE_SIZE) throw ... 防护
  • 返回 future 时注意生命周期:不要让 std::future 在线程池析构后被访问,否则会 std::terminate
  • 异常处理要在线程内捕获:worker 线程中未捕获异常会导致整个程序终止,可在 task 包装层加 try/catch
  • 考虑使用无锁队列(如 moodycamel::ConcurrentQueue):在极端高吞吐场景下减少锁争用

实际调用示例

提交普通函数、lambda、带返回值任务:

int main() {
    ThreadPool pool(4);

    // 提交无返回值任务
    pool.enqueue([]{ std::cout << "Hello from thread\n"; });

    // 提交带参数的 lambda
    pool.enqueue([](int x, const std::string& s) {
        std::cout << "x=" << x << ", s=" << s << "\n";
    }, 42, "world");

    // 提交有返回值任务,获取 future
    auto fut = pool.enqueue([] -> int {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        return 123;
    });

    std::cout << "Result: " << fut.get() << "\n"; // 阻塞等待结果

    return 0;
}

不复杂但容易忽略细节。按这个结构写,线程池就既安全又够用。


# ai  # c++  # ios  # stream  # 并发编程  # 无锁  # red  # if  # 封装  # try  # throw  # catch  # 循环  # Lambda  # 指针  # 线程  # 多线程  # Thread  # 并发  # function  # 对象  # 异步  # 是一个  # 返回值  # 长时间  # 要在  # 可在  # 已在  # 可选  # 而非  # 则会  # 绑定 


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


相关推荐: SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?  Python网络日志追踪_请求定位解析【教程】  如何在Golang中实现服务熔断与限流_Golang微服务容错与流控方法  c++ try_emplace用法_c++ map高效插入数据  MAC如何设置网卡MAC地址克隆_MAC终端修改物理地址与环境模拟【教程】  Mac如何解压zip和rar文件?(推荐免费工具)  PHP接收参数长度超限怎么办_修改postmaxsize设置教程【解答】  Python数据挖掘核心算法实践_聚类分类与特征工程  Windows如何拦截2345弹窗广告_Windows拦截2345弹窗方法【步骤】  如何在Golang中实现微服务服务拆分_Golang微服务拆分与接口管理方法  Mac如何与安卓手机传文件_Mac和Android设备互通【必备工具】  如何高效获取循环末次生成的 NumPy 数组最后一个元素(无需额外循环)  Windows10系统怎么查看显卡驱动_Win10设备管理器驱动更新  如何使用Golang sort排序切片_Golang sort排序方法示例  c++中如何对数组进行排序_c++数组排序算法汇总  如何在 ACF 中正确更新嵌套多层 Group 字段内的子字段  Linux如何安装Golang环境_Linux下Go语言开发包配置【方法】  Python装饰器复用技巧_通用能力解析【教程】  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  Win10怎样卸载自带Edge_Win10卸载Edge浏览器步骤【教程】  Win11怎么设置虚拟内存最佳大小_Windows11性能选项自定义分页文件  php订单日志怎么按状态筛选_php筛选不同状态订单日志教程【教程】  如何解决同一段404代码在不同主机上表现不一致的问题  Windows10如何更改鼠标灵敏度_Win10鼠标属性指针选项调节  微信JSAPI支付回调PHP怎么接收_处理JSAPI异步通知数据方法【指南】  Windows任务计划服务异常原因_任务调度失败的处理方案  如何在JavaScript中动态拼接PHP的base_url与jQuery变量  Win11怎么关闭触摸屏_禁用Win11笔记本触摸屏功能设置【教程】  如何在 PHP 中按相同键合并两个关联数组为二维数组  Win10如何更改任务栏高度_Windows10解锁任务栏调整大小  Win10怎么卸载金山毒霸_Win10彻底卸载金山毒霸方法【步骤】  c# 如何深拷贝和浅拷贝  Win11怎么制作U盘启动盘_Win11原版系统安装盘制作【详解】  php485返回数据不完整怎么办_php485数据分包重组处理方法【教程】  用lighttpd能运行php吗_lighttpd配置php步骤【教程】  Windows怎样拦截QQ浏览器广告_Windows拦截QQ浏览器广告方法【方法】  Python函数参数高级用法_默认值与可变参数解析【教程】  Win11怎么设置单手模式_Win11触控键盘布局调整教程【技巧】  php命令行怎么运行_通过CLI模式执行PHP脚本的步骤【说明】  windows如何备份注册表_windows导出和导入注册表文件教程  C#如何序列化对象为XML XmlSerializer用法  XML的“混合内容”是什么 怎么用DTD或XSD定义  PythonWeb前后端整合项目教程_FastAPIReact完整实例  mac怎么打开终端_MAC终端Terminal使用入门与常用命令【教程】  Windows10如何更改计算机工作组_Win10系统属性修改Workgroup  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  如何在 Go 中调用动态链接库(.so)中的函数  Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  PHP的FastAdmin架构适合二次开发吗_特点分析【介绍】  如何在Golang中实现邮件发送功能_Golang SMTP发送与错误处理示例 

 2026-01-04

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

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

点击免费数据支持

提交您的需求,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.