基于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装饰器的应用场景

    装饰器的应用场景 附加功能 数据的清理或添加: 函数参数类型验证 @require_ints 类似请求前拦截 数据格式转换 将函数返回字典改为 JSON/YAML 类似响应后篡改 为函数提供额外的数据 ...

  2. [CSP-S模拟测试]:C(倍增+数学)

    题目传送门(内部题152) 输入格式 第一行两个整数$N,Q$. 接下来一行$N$个整数,第$i$个为$a_i$. 接下来的$N-1$行,每行两个整数$u,v$.表示$u,v$之间有一条边. 接下来的 ...

  3. IntelliJ IDEA利用Maven下载所需的JAR包到项目中

    直接复制JetBrains/../conf/settings.xml后修改镜像出现问题,然后用了这里的settings.xml配置文件.

  4. Java实验报告(一)

    Java实验报告(一) 实验过程 1. 打印输出所有的"水仙花数",所谓"水仙花数"是指一个3位数,其中各位数字立方和等于该数本身.例如,153是一个" ...

  5. ionic3引用外部插件--百度地图及echart报表的使用

    前言 ionic3提供的组件已经相当丰富咯,但是事实上有些特殊的需求,比如使用百度地图,或者第三方插件echart报表插件是,就不能用传统的方式去使用第三方插件咯,如何在Ionic3项目中使用第三方J ...

  6. antd源码分析之——栅格(Grid)

    官方文档 https://ant.design/components/grid-cn/ 目录 一.antd中的Grid 代码目录 1.整体思路 2.less文件结构图(♦♦♦重要) 3.less实现逻 ...

  7. MySQL:行锁、表锁、乐观锁、悲观锁、读锁、写锁

    1.锁的分类 1.1从对数据操作的类型来分 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响. 结论1: --如果某一个会话 对A表加了read锁,则 该会话 可以对A表进行读操作 ...

  8. jdk1.8 HashMap源码分析(resize函数)

    // 扩容兼初始化 final Node<K, V>[] resize() { Node<K, V>[] oldTab = table; int oldCap = (oldTa ...

  9. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_1-1.SpringBoot整合微信支付开发在线教育视频站点介绍

    笔记 第一章项目介绍和前期准备 1.SpringBoot整合微信支付开发在线教育视频站点介绍     简介: 课程介绍,和小D课堂在线教育项目搭建开发 1.课程大纲介绍         2.微信支付项 ...

  10. 微信小程序tabBar的一个小坑

    开始接触微信小程序的项目开发时,自己想添加底部导航,按照文档的方法在app.json添加tabBar,结果编译不出,工具台也没错误提示. 尝试在网上搜一下,看到有碰到类似情况的,解决方法是:app.j ...