【C++11应用】基于C++11及std::thread实现的线程池
基于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实现的线程池的更多相关文章
- C++ 11 笔记 (五) : std::thread
这真是一个巨大的话题.我猜记录完善绝B需要一本书的容量. 所以..我只是略有了解,等以后用的深入了再慢慢补充吧. C++写多线程真是一个痛苦的事情,当初用过C语言的CreateThread,见过boo ...
- C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)
要写个tcp server / client的博客,想着先写个c++11多线程程序.方便后面写博客使用. 目前c++11中写多线程已经很方便了,不用再像之前的pthread_create,c++11中 ...
- Cocos2dx 3.0 过渡篇(二十六)C++11多线程std::thread的简单使用(上)
昨天练车时有一MM与我交替着练,聊了几句话就多了起来,我对她说:"看到前面那俩教练没?老色鬼两枚!整天调戏女学员."她说:"还好啦,这毕竟是他们的乐趣所在,你不认为教练每 ...
- C++11多线程std::thread的简单使用
在cocos2dx 2.0时代,我们使用的是pthread库,是一套用户级线程库,被广泛地使用在跨平台应用上.但在cocos2dx 3.0中并未发现有pthread的支持文件,原来c++11中已经拥有 ...
- 基于C++11的100行实现简单线程池
基于C++11的100行实现简单线程池 1 线程池原理 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小, ...
- C++11 并发指南------std::thread 详解
参考: https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Int ...
- 基于C++11的线程池,简洁且可以带任意多的参数
咳咳.C++11 加入了线程库,从此告别了标准库不支持并发的历史.然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池.信号量等.线程池(thread pool) ...
- 基于C++11的线程池(threadpool),简洁且可以带任意多的参数
咳咳.C++11 加入了线程库,从此告别了标准库不支持并发的历史.然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池.信号量等.线程池(thread pool) ...
- c++11中关于`std::thread`线程传参的思考
关于std::thread线程传参的思考 最重要要记住的一点是:参数要拷贝到线程独立内存中,不管是普通类型.还是引用类型. 对于传递参数是引用类型,需要注意: 1.当指向动态变量的指针(char *) ...
随机推荐
- Neo4j 简介 2019
Neo4j是一个世界领先的开源图形数据库,由 Java 编写.图形数据库也就意味着它的数据并非保存在表或集合中,而是保存为节点以及节点之间的关系. Neo4j 的数据由下面几部分构成: 节点边属性Ne ...
- 关于tensorflow里面的tf.contrib.rnn.BasicLSTMCell 中num_units参数问题
这里的num_units参数并不是指这一层油多少个相互独立的时序lstm,而是lstm单元内部的几个门的参数,这几个门其实内部是一个神经网络,答案来自知乎: class TRNNConfig(obje ...
- LoadLibrary(C:\soft\IDA 7.0\IDA 7.0\plugins\python64.dll) error: 找不到指定的模块。 C:\soft\IDA 7.0\IDA 7.0\plugins\python64.dll: can't load file LoadLibrary(C:\soft\IDA 7.0\IDA 7.0\plugins\python64.dll) erro
LoadLibrary(C:\soft\IDA 7.0\IDA 7.0\plugins\python64.dll) error: 找不到指定的模块. C:\soft\IDA 7.0\IDA 7.0\p ...
- MyBatis动态Sql 的使用
Mapper.xml提示: 1:mapper包中新建一个文件:mybatis-3-mapper.dtd 2:在web app libraries/mybatis.jar/org.apache.ibat ...
- 索引有B+索引和hash索引,各自的区别
Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B+树索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,那为什么大家不都用Hash索引而还要使用B+树索引呢? ...
- Python选择指定文件夹的文件然后复制出其中几个文件到新的文件夹
""" 要求: 1.读取cdm文件的所有子文件夹,然后每个文件夹里面是抽出一个一个mp3后缀的文件. 遍历所有的子文件,然后将这些mp3文件,保存到一个新的文件夹.文件夹 ...
- vsftp 上传550 Permission denied解决办法
在linux服务器上安装和配置了vsftp,添加用户然后现在用这个用户登录ftp成功,能下载,但是不能上传和删除,明明这个用户的主目录给了777权限了,但是始终无法上传 解决办法:是在/var/ftp ...
- Linux kernel device mapper
Device Mapper 是 Linux2.6 内核中支持逻辑卷管理的通用设备映射机制,它为实现用于存储资源管理的块设备驱动提供了一个高度模块化的内核架构,如图 1. 图1 Device Mappe ...
- 网络流,设备、插头和转接器建图(简单map的应用)
题意: 给你n个插座,m个设备,每台设备都有对应的插座,有k个转接器. 要求:求满足不能插上插座的用电器最少个数 solution: HINT:每种适配器都有无限个,所以建图的时候要改为INF. 答案 ...
- 数据结构之栈(stack)
1,栈的定义 栈:先进后出的数据结构,如下图所示,先进去的数据在底部,最后取出,后进去的数据在顶部,最先被取出. 栈常用操作: s=Stack() 创建栈 s.push(item) 将数据item放在 ...