C++11 ThreadPool总结
github两个实现
https://github.com/progschj/ThreadPool
- https://github.com/mtrebi/thread-pool
最先找到第一个的,看了一头雾水,过于难懂,第二个和第一个实现有些地方一样,但是文档写的很全。
其中enqueue的实现在看了example的代码之后,因为不熟悉拉姆达表达式,造成了很大的困扰。
ThreadPool pool(4);std::vector< std::future<int> > results;for(int i = 0; i < 8; ++i) {results.emplace_back(pool.enqueue([i] {std::cout << "hello " << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "world " << i << std::endl;return i*i;}));}for(auto && result: results)std::cout << result.get() << ' ';std::cout << std::endl;
因为在我的代码中enqueue的函数是c++的成员函数,如果用拉姆达表达式,当时就是不知道怎么写这个代码,最后看到https://github.com/lzpong/threadpool/blob/master/threadpool.h上的注释,使用std::mem_fn或者std::bind才会用了, git地址:https://github.com/lzpong/threadpool)的readme,多看看能帮助理解。
// 提交一个任务// 调用.get()获取返回值会等待任务执行完,获取返回值// 有两种方法可以实现调用类成员,// 一种是使用 bind: .commit(std::bind(&Dog::sayHello, &dog));// 一种是用 mem_fn: .commit(std::mem_fn(&Dog::sayHello), this)template<class F, class... Args>auto commit(F&& f, Args&&... args) ->future<decltype(f(args...))>{if (!_run) // stoped ??throw runtime_error("commit on ThreadPool is stopped.");using RetType = decltype(f(args...)); // typename std::result_of<F(Args...)>::type, 函数 f 的返回值类型auto task = make_shared<packaged_task<RetType()>>(bind(forward<F>(f), forward<Args>(args)...)); // 把函数入口及参数,打包(绑定)future<RetType> future = task->get_future();{ // 添加任务到队列lock_guard<mutex> lock{ _lock };//对当前块的语句加锁 lock_guard 是 mutex 的 stack 封装类,构造的时候 lock(),析构的时候 unlock()_tasks.emplace([task](){ // push(Task{...}) 放到队列后面(*task)();});}
#ifdef THREADPOOL_AUTO_GROWif (_idlThrNum < 1 && _pool.size() < THREADPOOL_MAX_NUM)addThread(1);
#endif // !THREADPOOL_AUTO_GROW_task_cv.notify_one(); // 唤醒一个线程执行return future;}
前面的例子中的代码,用的是Lambda的不完整写法: [capture list] {function body}
[i] {std::cout << "hello " << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "world " << i << std::endl;return i*i;
}
lamda表达式
这个例子里面用了一个lamda表达式,并不是说在调用的enqueue函数的时候,必须https://github.com/lzpong/threadpool用lambda表达式,开始我走入了个误区,lambda表达式写不好,总是不对,学习了Lambda表达时候才写对了,最后代码是这样写的:
初始化一个6个线程的线程池,用来处理N多data,这样一次就可以处理6份数据,处理完放到readyData队列,processTask是Clip的成员函数,可以用Lambda表达式,也可以用std::mem_fun或者std::bind。
threadPool.reset(new ThreadPool(6));
threadPool->init();
for (int idx = 0; idx < data.size(); idx++) {if (readyData[idx].empty()) {threadPool->submit([this, idx] {this->processTask(idx);});}
}
用std::mem_fn的写法
threadPool.reset(new ThreadPool(6));
threadPool->init();
for (int idx = 0; idx < data.size(); idx++) {if (readyData[idx].empty()) {threadPool->submit(std::mem_fn(&Clip::processTask), this, idx);}
}
用std::bind的写法
maskThreadPool.reset(new ThreadPool(6));
maskThreadPool->init();
for (int idx = 0; idx < data.size(); idx++) {if (readyData[idx].empty()) {threadPool->submit(std::bind(&Clip::processTask, this, idx));}
}
这里可以看出std::bind和std::mem_fn的区别,std::mem_fn在外面跟了this指针和其他参数,std::bind中跟了所有参数。
用lambda表达式
threadPool.reset(new ThreadPool(6));
threadPool->init();
for (int idx = 0; idx < data.size(); idx++) {if (readyData[idx].empty()) {threadPool->submit([this, idx] {this->processTask(idx);});}
}
Lambda 表达式
简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。这一用法跟所谓 λ 演算(题目说明里的维基链接)的关系,有点像原子弹和质能方程的关系,差别其实还是挺大的。
Lambda表达式完整的声明格式如下:
[capture list] (params list) mutable exception-> return type { function body }
各项具体含义如下
- capture list:捕获外部变量列表
- params list:形参列表
- mutable指示符:用来说用是否可以修改捕获的变量
- exception:异常设定
- return type:返回类型
- function body:函数体
此外,我们还可以省略其中的某些成分来声明“不完整”的Lambda表达式,常见的有以下几种:
序号 |
格式 |
1 |
[capture list] (params list) -> return type {function body} |
2 |
[capture list] (params list) {function body} |
3 |
[capture list] {function body} |
std::bind绑定普通函数
- bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (my_divide, x, y)等价于std::bind (&my_divide,x, y);
double my_divide (double x, double y) {return x/y;}
auto fn_half = std::bind (my_divide, x, y);
std::bind绑定一个成员函数
- bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
class Foo {void print_sum(int n1, int n2) {std::cout << n1+n2 << '\n';}int data = 10;
};
int main() {Foo foo;auto f = std::bind(&Foo::print_sum, &foo, 95, 5);f(5, 95); // 100
}
参考:
解读github上流行的ThreadPool源码
- C-Thread-Pool-使用解析
- C++11 中的std::function和std::bind
C++11 ThreadPool总结相关推荐
- c语言捕鱼达人源码,用捕鱼达人去理解C中的多线程.doc
用<捕鱼达人>去理解C 中的多线程 线程是进程中某个单一顺序的控制流,是程序运行中的调度单位,是程序执行流的最小单位,一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成. ...
- 【java 高并发编程之JUC】2w字带你JUC从入门到精通
点击查看脑图目录地址,实时更新 1 什么是 JUC 1.1 JUC 简介 在 Java 中,线程部分是一个重点,本篇文章说的 JUC 也是关于线程的.JUC 就是 java.util .concurr ...
- Redis分布式锁详解
Redis分布式锁详解 1. 分布式所概述 1.1 分布式锁 2. 缓存数据库Redis 2.1 redis简介 2.2 Springboot整合Redis两种方式 3. 实现验证 3.1 环境准备 ...
- 使用C++11封装线程池ThreadPool
2019独角兽企业重金招聘Python工程师标准>>> 读本文之前,请务必阅读: 使用C++11的function/bind组件封装Thread以及回调函数的使用 Linux组件封装 ...
- threadpool的数量_多线程之旅(11)_如何限制系统线程池ThreadPool的最大最小并发数量_SetMaxThreads/SetMinThreads用法...
ThreadPool有两个设置线程池并发数量的方法,分别是: ThreadPool.SetMinThreads(int workerThreads, int completionPortThreads ...
- C++11中头文件thread的使用
C++11中加入了<thread>头文件,此头文件主要声明了std::thread线程类.C++11的标准类std::thread对线程进行了封装.std::thread代表了一个线程对象 ...
- 简单ThreadPool实现
由于最近需要用多线程处理一些问题,一开始我用了.net默认的ThreadPool,感觉不是很适合.于是我自己实现了一个简单的ThreadPool. 写的比较简单,有兴趣的朋友一起看看,共同改进. 代码 ...
- C#并行开发_Thread/ThreadPool, Task/TaskFactory, Parallel
大家好,本次讨论的是C#中的并行开发,给力吧,随着并行的概念深入,哥也赶上这个潮流了,其实之前讨论C#的异步调用或者C#中BeginInvoke或者Invoke都已经涉及了部分本篇的内容. 参考书目: ...
- 艾伟:WCF从理论到实践(11)-异步
本系列文章导航 WCF从理论到实践(1):揭开神秘面纱 WCF从理论到实践(2):决战紫禁之巅 WCF从理论到实践(3):八号当铺之黑色契约 WCF从理论到实践(4):路在何方 WCF从理论到实践(5 ...
最新文章
- 【Linux】文件特殊权限 SUID/SGID/Sticky Bit
- 如何写优雅的SQL原生语句?
- 将服务端移植到Linux和MAC OS
- 分析函数在数据分析中的应用
- 前端学习(1336):从数据库查询文档
- spring 框架(一)
- 蚂蚁金服冯柯:下一个十年,核心自研技术将迎来黄金发展期
- 618买手机哪家强?苹果官方也来打折促销了
- dede index.php权限_织梦实现全站动态,限制只有会员才能查看
- Android 8.1 SystemUI之状态栏、下拉菜单通知、导航栏分析(一)
- ADB 命令知多少?详细 ADB 命令大全来啦
- TXT文本文件中批量替代回车符号
- womic网络错误_无线麦克风WO Mic
- 【华人学者风采】聂飞平 西北工业大学
- kali安装磊科NW392教程
- day_7:代理使用
- acm-(辗转相除法、丢番图方程)2020 China Collegiate Programming Contest Qinhuangdao Site I. Interstellar Hunter
- 问题 E: 天宝便利店
- 6种品牌打印机介绍及打印机旗舰店推荐
- 计算机sd模式怎么打游戏,绝地求生提升fps方法,绝地求生吃鸡游戏提高帧数优化教程(图文)...
热门文章
- pycharm批量注释
- 【Java应用程序开发】【期末复习题】【2022秋】【答案仅供参考】
- SSM框架优缺点和springboot 比起优缺点是什么?
- 解决The plain HTTP request was sent to HTTPS port
- 数学小游戏:原创字谜几则
- error C2872: 'ULONG_PTR' : ambiguous symbol
- CentOS系统重新删除磁盘分区和挂载、开机自启(大于2T做法)
- 电脑怎么用照片做视频?哪个软件简单好用?3步教你轻松制作!
- 神经网络与深度学习(入门篇)
- 老师傅传授,数控车床对刀步骤