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

线程池源码:

#pragma once
#include <functional>
#include <deque>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <memory>
#include <cassert> /*
* Example:
*
* // 初始回调
* void InitCb() {
* static int i = 0;
* printf("InitCb: %d\n", i++);
* }
*
* // 任务函数
* void TaskCb() {
* static int i = 0;
* printf("TaskCb: %d\n", i++);
* }
*
* // 实例化大小为10的线程池
* std::unique_ptr<ThreadPool> upTp(new ThreadPool(10, std::bind(InitCb)));
* // 启动5个线程
* upTp->Start(5);
* do {
* // 投递任务进行处理
* upTp->InputTask(std::bind(TaskCb));
* } while(true);
*
*/
class ThreadPool
{
public:
ThreadPool(const ThreadPool& other) = delete;
ThreadPool& operator=(const ThreadPool& other) = delete;
using Task = std::function<void()>; ThreadPool(size_t max_queue_size, Task cb)
: cb_(std::move(cb)),
max_queue_size_(max_queue_size),
running_(false)
{
} ~ThreadPool()
{
if (running_)
{
Stop();
}
} void Start(unsigned num_threads)
{
assert(threads_.empty());
running_ = true;
threads_.reserve(num_threads);
for (auto i = 0; i < num_threads; ++i)
{
threads_.emplace_back(new std::thread(&ThreadPool::Process, this, i));
} if (num_threads == 0 && cb_)
{
cb_();
}
} void Stop()
{
{
std::lock_guard<std::mutex> lk(mtx_);
running_ = false;
not_empty_cond_.notify_all();
} for (auto& th : threads_)
{
th->join();
}
} void InputTask(Task task)
{
if (threads_.empty())
{
task();
}
else
{
std::unique_lock<std::mutex> lk(mtx_);
while (IsFull())
{
not_full_cond_.wait(lk);
}
assert(!IsFull()); queue_.push_back(std::move(task));
not_empty_cond_.notify_one();
}
} private:
void Process(unsigned nId)
{
printf("current thread id: %d\n", nId);
try
{
if (cb_)
{
cb_();
} while (running_)
{
Task task(Pop());
if (task)
{
task();
}
}
}
catch (...)
{
// TODO
throw;
}
} Task Pop()
{
std::unique_lock<std::mutex> lk(mtx_);
while (queue_.empty() && running_)
{
not_empty_cond_.wait(lk);
} Task task;
if (!queue_.empty())
{
task = queue_.front();
queue_.pop_front();
if (max_queue_size_ > 0)
{
not_full_cond_.notify_one();
}
}
return task;
} bool IsFull()
{
return max_queue_size_ > 0 && queue_.size() >= max_queue_size_;
} mutable std::mutex mtx_;
std::condition_variable not_empty_cond_;
std::condition_variable not_full_cond_;
Task cb_;
std::vector<std::unique_ptr<std::thread>> threads_;
std::deque<Task> queue_;
size_t max_queue_size_;
bool running_;
};

参考:陈硕——《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实现的简易记牌器的demo

    实现功能很简单: 初始时 1到10 以及 jkq各 4张,大小王 共两张 只要输入相应的牌号:1到10,例如 >>1     J.K.Q :例如>>j     >> ...

  2. jquery转换js

    刚离职,一直忙于弄简历,整理面试题.今天得空吧前几天学习复习的jq基础知识整理一下,长时间不用还真的忘记了.所有在深入学习中也不要忘记复习之前的知识.做巩固,老话说的好打好根基才能盖好房.基础知识过后 ...

  3. scarpy crawl 爬取微信小程序文章(将数据通过异步的方式保存的数据库中)

    import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider ...

  4. JVM模型及内存溢出

    一.JVM截图及概念 图1:JVM虚拟机运行时数据区域概念模型 1.程序计数器:内存空间中的一块小区域,作为当前线程所执行的字节码的行号指示器,注:如果是native方法,计数器为空 2.虚拟机栈:线 ...

  5. 【软件工程】Beta冲刺(5/5)

    链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 将数据分析以可视化形式展示出来 新增数据分析展示等功能API 服务器后端部署, ...

  6. Arcgis python输出当前窗口

    import arcpy mxd = arcpy.mapping.MapDocument("CURRENT") mxdfile=arcpy.GetParameterAsText(0 ...

  7. Linux 下安装 Tomcat 服务器和部署 Web 应用

    一.上传Tomcat服务器 二.安装Tomcat服务器 2.1.解压tomcat服务器压缩包 2.2.配置环境变量 tomcat服务器运行时是需要JDK支持的,所以必须配置好JDK用到的那些环境变量 ...

  8. laravel-5.6路由命名

    1.第一种:通过route路由中的as关键字来实现 1 Route::get('api/user',['as'='web.user'],'messageController@userInformati ...

  9. incredibuild(分布式任务软件)脚本

    IncrediBuild 可以在Server段通过修改单个任务的进程上限来实现提升任务执行速度. IncredBuild本机版也可以用来进行本机实现多线程任务分发,这样可以充分利用多核资源. 提交分布 ...

  10. C语言处理CSV数据

    以下代码为博客 <Python的并行求和例子>: http://www.cnblogs.com/instant7/p/4312786.html 中并行python代码的C语言重写版. 用C ...