基于C++11及std::thread实现的线程池

线程池源码:

  1. #pragma once
  2. #include <functional>
  3. #include <deque>
  4. #include <thread>
  5. #include <mutex>
  6. #include <condition_variable>
  7. #include <vector>
  8. #include <memory>
  9. #include <cassert>
  10. /*
  11. * Example:
  12. *
  13. * // 初始回调
  14. * void InitCb() {
  15. * static int i = 0;
  16. * printf("InitCb: %d\n", i++);
  17. * }
  18. *
  19. * // 任务函数
  20. * void TaskCb() {
  21. * static int i = 0;
  22. * printf("TaskCb: %d\n", i++);
  23. * }
  24. *
  25. * // 实例化大小为10的线程池
  26. * std::unique_ptr<ThreadPool> upTp(new ThreadPool(10, std::bind(InitCb)));
  27. * // 启动5个线程
  28. * upTp->Start(5);
  29. * do {
  30. * // 投递任务进行处理
  31. * upTp->InputTask(std::bind(TaskCb));
  32. * } while(true);
  33. *
  34. */
  35. class ThreadPool
  36. {
  37. public:
  38. ThreadPool(const ThreadPool& other) = delete;
  39. ThreadPool& operator=(const ThreadPool& other) = delete;
  40. using Task = std::function<void()>;
  41. ThreadPool(size_t max_queue_size, Task cb)
  42. : cb_(std::move(cb)),
  43. max_queue_size_(max_queue_size),
  44. running_(false)
  45. {
  46. }
  47. ~ThreadPool()
  48. {
  49. if (running_)
  50. {
  51. Stop();
  52. }
  53. }
  54. void Start(unsigned num_threads)
  55. {
  56. assert(threads_.empty());
  57. running_ = true;
  58. threads_.reserve(num_threads);
  59. for (auto i = 0; i < num_threads; ++i)
  60. {
  61. threads_.emplace_back(new std::thread(&ThreadPool::Process, this, i));
  62. }
  63. if (num_threads == 0 && cb_)
  64. {
  65. cb_();
  66. }
  67. }
  68. void Stop()
  69. {
  70. {
  71. std::lock_guard<std::mutex> lk(mtx_);
  72. running_ = false;
  73. not_empty_cond_.notify_all();
  74. }
  75. for (auto& th : threads_)
  76. {
  77. th->join();
  78. }
  79. }
  80. void InputTask(Task task)
  81. {
  82. if (threads_.empty())
  83. {
  84. task();
  85. }
  86. else
  87. {
  88. std::unique_lock<std::mutex> lk(mtx_);
  89. while (IsFull())
  90. {
  91. not_full_cond_.wait(lk);
  92. }
  93. assert(!IsFull());
  94. queue_.push_back(std::move(task));
  95. not_empty_cond_.notify_one();
  96. }
  97. }
  98. private:
  99. void Process(unsigned nId)
  100. {
  101. printf("current thread id: %d\n", nId);
  102. try
  103. {
  104. if (cb_)
  105. {
  106. cb_();
  107. }
  108. while (running_)
  109. {
  110. Task task(Pop());
  111. if (task)
  112. {
  113. task();
  114. }
  115. }
  116. }
  117. catch (...)
  118. {
  119. // TODO
  120. throw;
  121. }
  122. }
  123. Task Pop()
  124. {
  125. std::unique_lock<std::mutex> lk(mtx_);
  126. while (queue_.empty() && running_)
  127. {
  128. not_empty_cond_.wait(lk);
  129. }
  130. Task task;
  131. if (!queue_.empty())
  132. {
  133. task = queue_.front();
  134. queue_.pop_front();
  135. if (max_queue_size_ > 0)
  136. {
  137. not_full_cond_.notify_one();
  138. }
  139. }
  140. return task;
  141. }
  142. bool IsFull()
  143. {
  144. return max_queue_size_ > 0 && queue_.size() >= max_queue_size_;
  145. }
  146. mutable std::mutex mtx_;
  147. std::condition_variable not_empty_cond_;
  148. std::condition_variable not_full_cond_;
  149. Task cb_;
  150. std::vector<std::unique_ptr<std::thread>> threads_;
  151. std::deque<Task> queue_;
  152. size_t max_queue_size_;
  153. bool running_;
  154. };

参考:陈硕——《Linux多线程服务器编程》

【C++11应用】基于C++11及std::thread实现的线程池的更多相关文章

  1. C++ 11 笔记 (五) : std::thread

    这真是一个巨大的话题.我猜记录完善绝B需要一本书的容量. 所以..我只是略有了解,等以后用的深入了再慢慢补充吧. C++写多线程真是一个痛苦的事情,当初用过C语言的CreateThread,见过boo ...

  2. C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)

    要写个tcp server / client的博客,想着先写个c++11多线程程序.方便后面写博客使用. 目前c++11中写多线程已经很方便了,不用再像之前的pthread_create,c++11中 ...

  3. Cocos2dx 3.0 过渡篇(二十六)C++11多线程std::thread的简单使用(上)

    昨天练车时有一MM与我交替着练,聊了几句话就多了起来,我对她说:"看到前面那俩教练没?老色鬼两枚!整天调戏女学员."她说:"还好啦,这毕竟是他们的乐趣所在,你不认为教练每 ...

  4. C++11多线程std::thread的简单使用

    在cocos2dx 2.0时代,我们使用的是pthread库,是一套用户级线程库,被广泛地使用在跨平台应用上.但在cocos2dx 3.0中并未发现有pthread的支持文件,原来c++11中已经拥有 ...

  5. 基于C++11的100行实现简单线程池

    基于C++11的100行实现简单线程池 1 线程池原理 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小, ...

  6. C++11 并发指南------std::thread 详解

    参考: https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Int ...

  7. 基于C++11的线程池,简洁且可以带任意多的参数

    咳咳.C++11 加入了线程库,从此告别了标准库不支持并发的历史.然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池.信号量等.线程池(thread pool) ...

  8. 基于C++11的线程池(threadpool),简洁且可以带任意多的参数

    咳咳.C++11 加入了线程库,从此告别了标准库不支持并发的历史.然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池.信号量等.线程池(thread pool) ...

  9. c++11中关于`std::thread`线程传参的思考

    关于std::thread线程传参的思考 最重要要记住的一点是:参数要拷贝到线程独立内存中,不管是普通类型.还是引用类型. 对于传递参数是引用类型,需要注意: 1.当指向动态变量的指针(char *) ...

随机推荐

  1. 秒懂数据类型的真谛—Python基础前传(4)

    一切编程语言都是人设计的,既然是人设计的,那么设计各种功能的时候就一定会有它的道理,那么设计数据类型的用意是什么呢? (一) 基本数据类型 基本数据类型: 数字 int 字符串 str 布尔值 boo ...

  2. deep sort

    目录   1. 准备代码与数据 deep_sort开源代码 克隆到本地服务器 git clone https://github.com/nwojke/deep_sort.git 下载MOT16数据集( ...

  3. redis慢查询笔记

    慢查询 生命周期 两个配置 三个命令 运维经验 生命周期 1.发送命令 2,排队执行命令因为单线程 3.执行命令 4.返回结果 慢查询发生在第三阶段 客户端超时并不一定有慢查询,但慢查询是客户端超时的 ...

  4. 如何使用SendGrid发送邮件

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  5. HashMap简单介绍

    哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表. 一.什么是哈希表 在讨论哈希表之 ...

  6. 用单元测试来调试SilverFish AI

    [TestFixture] public class AiTest { [Test] public void Test() { Settings.Instance.LogFolderPath = @& ...

  7. zabbix自定义监控,自定义图表。

    zabbix server:hostname=Zabbix server ip:192.168.100.7 zabbix agent: hostname=host3 ip:192.168.100.3 ...

  8. CSS3 新特性

    ~平时喜欢逛博客,看别人的学习总结和遇到的问题解决办法,恰好最近在做书签整理,翻到了之前一个前辈移动前端的总结,所以我就按他的总结模块对自己的知识进行了梳理,不过由于都是手写的,为了方便,下面的都是平 ...

  9. C# List中的ForEach

    ; List<string> aaa = new List<string>(){ "aaa", "bbb" }; aaa.ForEach ...

  10. leetcode1283 使结果不超过阈值的最小除数

    这道题第一思路是用二分查找 因为使用二分法:所以复杂度为O(n*logk), k介于 left=sum/threshold(向下取整) 和 right=num_max之间:而right<=10^ ...