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总结相关推荐

  1. c语言捕鱼达人源码,用捕鱼达人去理解C中的多线程.doc

    用<捕鱼达人>去理解C 中的多线程 线程是进程中某个单一顺序的控制流,是程序运行中的调度单位,是程序执行流的最小单位,一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成. ...

  2. 【java 高并发编程之JUC】2w字带你JUC从入门到精通

    点击查看脑图目录地址,实时更新 1 什么是 JUC 1.1 JUC 简介 在 Java 中,线程部分是一个重点,本篇文章说的 JUC 也是关于线程的.JUC 就是 java.util .concurr ...

  3. Redis分布式锁详解

    Redis分布式锁详解 1. 分布式所概述 1.1 分布式锁 2. 缓存数据库Redis 2.1 redis简介 2.2 Springboot整合Redis两种方式 3. 实现验证 3.1 环境准备 ...

  4. 使用C++11封装线程池ThreadPool

    2019独角兽企业重金招聘Python工程师标准>>> 读本文之前,请务必阅读: 使用C++11的function/bind组件封装Thread以及回调函数的使用 Linux组件封装 ...

  5. threadpool的数量_多线程之旅(11)_如何限制系统线程池ThreadPool的最大最小并发数量_SetMaxThreads/SetMinThreads用法...

    ThreadPool有两个设置线程池并发数量的方法,分别是: ThreadPool.SetMinThreads(int workerThreads, int completionPortThreads ...

  6. C++11中头文件thread的使用

    C++11中加入了<thread>头文件,此头文件主要声明了std::thread线程类.C++11的标准类std::thread对线程进行了封装.std::thread代表了一个线程对象 ...

  7. 简单ThreadPool实现

    由于最近需要用多线程处理一些问题,一开始我用了.net默认的ThreadPool,感觉不是很适合.于是我自己实现了一个简单的ThreadPool. 写的比较简单,有兴趣的朋友一起看看,共同改进. 代码 ...

  8. C#并行开发_Thread/ThreadPool, Task/TaskFactory, Parallel

    大家好,本次讨论的是C#中的并行开发,给力吧,随着并行的概念深入,哥也赶上这个潮流了,其实之前讨论C#的异步调用或者C#中BeginInvoke或者Invoke都已经涉及了部分本篇的内容. 参考书目: ...

  9. 艾伟:WCF从理论到实践(11)-异步

    本系列文章导航 WCF从理论到实践(1):揭开神秘面纱 WCF从理论到实践(2):决战紫禁之巅 WCF从理论到实践(3):八号当铺之黑色契约 WCF从理论到实践(4):路在何方 WCF从理论到实践(5 ...

最新文章

  1. 【Linux】文件特殊权限 SUID/SGID/Sticky Bit
  2. 如何写优雅的SQL原生语句?
  3. 将服务端移植到Linux和MAC OS
  4. 分析函数在数据分析中的应用
  5. 前端学习(1336):从数据库查询文档
  6. spring 框架(一)
  7. 蚂蚁金服冯柯:下一个十年,核心自研技术将迎来黄金发展期
  8. 618买手机哪家强?苹果官方也来打折促销了
  9. dede index.php权限_织梦实现全站动态,限制只有会员才能查看
  10. Android 8.1 SystemUI之状态栏、下拉菜单通知、导航栏分析(一)
  11. ADB 命令知多少?详细 ADB 命令大全来啦
  12. TXT文本文件中批量替代回车符号
  13. womic网络错误_无线麦克风WO Mic
  14. 【华人学者风采】聂飞平 西北工业大学
  15. kali安装磊科NW392教程
  16. day_7:代理使用
  17. acm-(辗转相除法、丢番图方程)2020 China Collegiate Programming Contest Qinhuangdao Site I. Interstellar Hunter
  18. 问题 E: 天宝便利店
  19. 6种品牌打印机介绍及打印机旗舰店推荐
  20. 计算机sd模式怎么打游戏,绝地求生提升fps方法,绝地求生吃鸡游戏提高帧数优化教程(图文)...

热门文章

  1. pycharm批量注释
  2. 【Java应用程序开发】【期末复习题】【2022秋】【答案仅供参考】
  3. SSM框架优缺点和springboot 比起优缺点是什么?
  4. 解决The plain HTTP request was sent to HTTPS port
  5. 数学小游戏:原创字谜几则
  6. error C2872: 'ULONG_PTR' : ambiguous symbol
  7. CentOS系统重新删除磁盘分区和挂载、开机自启(大于2T做法)
  8. 电脑怎么用照片做视频?哪个软件简单好用?3步教你轻松制作!
  9. 神经网络与深度学习(入门篇)
  10. 老师傅传授,数控车床对刀步骤