当前位置: 首页 > news >正文

C++11实现线程池

这是一个线程池实现,结合了多个异步编程示例。让我详细解释每个部分:

整体结构

代码展示了多种 C++11 异步编程技术的用法,最后实现了一个完整的线程池。

各部分详解

1.第一部分:std::async 的基本用法

void task(const char* name) { std::cout << name << " 开始执行,线程ID: " << std::this_thread::get_id() << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << name << " 完成" << std::endl; }
  • 演示了std::async的两种启动策略:

    • std::launch::async: 立即在新线程中执行

    • std::launch::deferred: 延迟执行(调用get()时才执行)

2.第二部分:std::future 获取结果

std::future<int> result = std::async(std::launch::async, simpleTask); int value = result.get();
  • 展示了如何通过std::future::get()获取异步任务结果

  • 注意:get()只能调用一次

3.第三部分:std::promise 和 std::future

std::promise<double> prom; auto fut = prom.get_future(); std::thread t(computeSqrt, std::move(prom), 9);
  • std::promise用于在线程间传递结果

  • 可以从 promise 获取 future

  • 可以在另一个线程中设置值或异常

4.第四部分:std::shared_future

std::shared_future<int> sharedFut = prom.get_future().share();
  • 多个线程可以共享同一个 future

  • get()可以多次调用

  • 通过share()从普通 future 创建 shared_future

5.第五部分:std::packaged_task

std::packaged_task<int(int)> task([](int x) { return x * x; }); std::future<int> result = task.get_future(); std::thread worker(std::move(task), 5);
  • 包装可调用对象

  • 可以获取关联的 future

  • 可以传递给线程执行

6.第六部分:任务队列和条件变量

void taskRunner(std::queue<std::packaged_task<int()>>& taskqueue, ...) { while (true) { std::unique_lock<std::mutex> lock(task_mtx); cv.wait(lock, [&taskqueue] { return !taskqueue.empty(); }); // 处理任务 } }
  • 使用std::condition_variable实现线程间通信

  • 工作线程等待任务,有任务时被唤醒

  • 主线程添加任务到队列

7.第七部分:并行计算示例(计算素数)

futures.push_back( std::async(std::launch::async, countPrimes, start, end) ); // 收集结果 int total1 = 0; for (auto& fut : futures) { total1 += fut.get(); }
  • 将大任务拆分成多个子任务

  • 使用std::async并行计算

  • 收集所有结果并汇总

8.第八部分:完整的 ThreadPool 类

这是最重要的部分,实现了一个生产级别的线程池

核心设计
class ThreadPool { private: std::vector<std::thread> workers; // 工作线程 std::queue<std::function<void()>> tasks; // 任务队列 std::mutex queue_mutex; // 队列互斥锁 std::condition_variable condition; // 条件变量 bool stop; // 停止标志 };
关键方法
  1. 构造函数:创建指定数量的工作线程

  2. enqueue 方法:提交任务到线程池

  3. 析构函数:优雅关闭线程池

模板方法 enqueue
template<class F, class... Args> auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> { // 1. 推导返回类型 using return_type = typename std::result_of<F(Args...)>::type; // 2. 创建 packaged_task auto task = std::make_shared<std::packaged_task<return_type()>>( std::bind(std::forward<F>(f), std::forward<Args>(args)...) ); // 3. 获取 future std::future<return_type> res = task->get_future(); // 4. 将任务添加到队列 { std::unique_lock<std::mutex> lock(queue_mutex); tasks.emplace([task]() { (*task)(); }); } // 5. 通知一个等待的线程 condition.notify_one(); return res; }
工作线程循环
for (;;) { std::function<void()> task; { std::unique_lock<std::mutex> lock(this->queue_mutex); // 等待条件:线程池停止 或 队列不为空 this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); // 线程池停止且队列为空 -> 退出 if (this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); } task(); // 执行任务 }

9.主函数测试

int main() { const int MAX = 100000000; const int THREADS = 8; ThreadPool pool(8); // 创建线程池 std::vector<std::future<int>> futures; // 拆分任务并提交到线程池 for (int i = 0; i < THREADS; ++i) { int start = i * chunk + 1; int end = (i == THREADS - 1) ? MAX : (i + 1) * chunk; futures.push_back( pool.enqueue(countPrimes, start, end) // 提交任务 ); } // 收集结果 int total1 = 0; for (auto& fut : futures) { total1 += fut.get(); // 阻塞等待结果 } std::cout << "素数总数: " << total1 << std::endl; return 0; }

关键特性总结

  1. 线程安全:使用互斥锁保护共享资源

  2. 任务队列:FIFO 顺序执行任务

  3. 条件变量:高效等待任务

  4. 优雅关闭:析构时等待所有任务完成

  5. 异常安全:任务异常不会影响线程池

  6. 通用接口:支持任意可调用对象

  7. 返回结果:通过std::future获取任务结果

使用场景

  • 需要大量并发执行的小任务

  • 避免频繁创建/销毁线程的开销

  • 控制并发线程数量

  • 实现生产者-消费者模式

这个线程池实现是生产可用的,包含了异常处理、资源管理和优雅关闭等关键特性。

http://www.jsqmd.com/news/359147/

相关文章:

  • 金碧荷,云南特产,是春兰与豆瓣兰的自然串种瑰宝
  • MySQL 索引失效跑不出这 8 个场景
  • 墨江双龙烧烤城(每周3周6)赶集才有人
  • 数字图像处理篇---图像的小波变换
  • 【计算机毕业设计案例】基于微信小程序的健康饮食推荐系统基于springboot+小程序的个性化食谱推荐系统小程序(程序+文档+讲解+定制)
  • 技术面试官视角:除了代码,更看重候选人的哪些潜质与特质?
  • 数字图像处理---压缩编码
  • 线上 OOM 了!热乎的!
  • 【计算机毕业设计案例】基于springboot+小程序的自助停车缴费系统小程序基于微信小程序的自助停车缴费系统停车场车位预约(程序+文档+讲解+定制)
  • 手写三高支付网关的设计与实现:基于Java17与Netty的核心架构!
  • 数字图像处理篇---路径模糊
  • 计算机小程序毕设实战-基于springboot+小程序的高校校园信息交流平台小程序设计与实现基于微信小程序的智慧校园平台的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 数字图像处理篇---光圈模糊
  • 2026激光切管机十大品牌实力排名(行业标杆TOP10) - 匠言榜单
  • 小程序计算机毕设之基于springboot+小程序的自助停车缴费系统小程序的设计与实现基于SpringBoot的停车管理微信小程序系统(完整前后端代码+说明文档+LW,调试定制等)
  • C++11 异步编程入门教程
  • 盒马鲜生礼品卡回收避坑指南,安全变现看这篇 - 京顺回收
  • 小程序毕设项目:基于springboot+小程序的自助停车缴费系统小程序的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 数字图像处理篇---场模糊
  • 【毕业设计】基于springboot+小程序的自助停车缴费系统小程序的设计与实现(源码+文档+远程调试,全bao定制等)
  • 数字图像处理篇---高斯模糊
  • 数据中台建设中的10大常见坑点及避坑指南
  • 数字图像处理篇---移轴模糊
  • 小程序计算机毕设之基于微信小程序的智慧校园平台的设计与实现基于springboot+小程序的高校校园信息交流平台小程序设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • 【计算机毕业设计案例】基于SpringBoot的停车管理微信小程序系统基于springboot+小程序的自助停车缴费系统小程序的设计与实现(程序+文档+讲解+定制)
  • 详细介绍:SpringCloud实战十三:Gateway之 Spring Cloud Gateway 动态路由
  • 什么是WLAN
  • 五年筑梦,代码伴行:我的技术创作之路
  • 2026.2.8
  • python作业1