多线程 等待一次性事件 packaged_task用法

背景:不是很明白,不知道为了解决什么业务场景,感觉std::asynck可以优雅的搞定一切,一次等待性事件,为什么还有个packaged_task。

用法:和std::async一样,也能够返回std::future,通过调用get_future方法。也可以通过future得到线程的返回值。

特点:

1,是个模板类,模板类型是个方法类型,比如double(int),有一个参数,类型是int,返回值类型是double。

  1. std::packaged_task<double(int)> task(func);//func是个方法,有一个参数,类型是int,返回值类型是double

2,直接执行std::packaged_task的对象task时,不是异步执行,是在原来的线程上阻塞执行,也就是说,只有task执行结束后,后面的代码才能被执行,也就是说不是多线程执行。

  1. std::packaged_task<std::string(int)> task1(call_texi);
  2. std::future<std::string> ft1 = task1.get_future();
  3. task1(100);//task1执行完成后,才能执行下面的打印输出的代码,不是在新的线程里执行task1(100)
  4. std::cout << "111111111111111111111111111111" << std::endl;

3,作为线程的参数时,用std::ref。把task放在线程里后,就是异步执行了。

  1. std::packaged_task<std::string(int)> task1(call_texi);
  2. std::future<std::string> ft1 = task1.get_future();
  3. std::thread t1(std::ref(task1), 100);
  4. t1.detach();//task1(100)是异步执行,也就是在新的线程里执行。
  5. std::cout << "111111111111111111111111111111" << std::endl;

代码:

  1. #include <deque>
  2. #include <mutex>
  3. #include <future>
  4. #include <thread>
  5. #include <iostream>
  6. #include <unistd.h>
  7. #include <string>
  8. //#include <utility>
  9. std::mutex mut;
  10. std::deque<std::packaged_task<std::string(int)>> tasks;
  11. void manage_tasks(){
  12. while(true){
  13. sleep(1);
  14. //std::cout << "please wait for a moument" << std::endl;
  15. std::packaged_task<std::string(int)> task;
  16. {
  17. std::lock_guard<std::mutex> lg(mut);
  18. if(tasks.empty()) continue;
  19. std::cout << "----------------------not empty---------------" << std::endl;
  20. task = std::move(tasks.front());
  21. tasks.pop_front();
  22. }
  23. task(1);
  24. //std::string s = task(10);
  25. }
  26. }
  27. template<typename Call>
  28. std::future<std::string> add_task(Call ca){
  29. std::cout << "----------------------add_task---------------" << std::endl;
  30. std::packaged_task<std::string(int)> task(ca);
  31. std::future<std::string> ret = task.get_future();
  32. std::lock_guard<std::mutex> lg(mut);
  33. tasks.push_back(std::move(task));
  34. return ret;
  35. }
  36. std::string call_texi(int i = 0){
  37. std::cout << "-------------jiaoche---------------" << std::endl;
  38. if(i == 1){
  39. return "aaa";
  40. }else{
  41. return "bbb";
  42. }
  43. }
  44. std::string call_zhuanche(int i){
  45. std::cout << "zhuanche:" << i << std::endl;
  46. return std::to_string(i);
  47. }
  48. int main(){
  49. std::thread background_thread(manage_tasks);
  50. background_thread.detach();
  51. std::future<std::string> fut1 = add_task(call_texi);
  52. std::cout << fut1.get() << std::endl;
  53. std::future<std::string> fut2 = add_task(call_zhuanche);
  54. std::cout << fut2.get() << std::endl;
  55. pthread_exit(NULL);
  56. }

github源代码

编译方法:

  1. g++ -g XXX.cpp -std=c++11 -pthread

运行结果:

  1. ----------------------add_task---------------
  2. ----------------------not empty---------------
  3. -------------jiaoche---------------
  4. aaa
  5. ----------------------add_task---------------
  6. ----------------------not empty---------------
  7. zhuanche:1
  8. 1

代码分析:在队列里保存std::packaged_task,启动一个后台线程background_thread,上锁,监视队列里是否有了新的task,有了新的task,就取出来用右值赋值的方式,然后出队这个task,解锁。执行这个task。

迷惑点:

  • add_task的调用时点,是可以知道传递什么参数的,但是调用add_task时,由于语法的限制不能够把参数传递给call_zhuanche方法或者call_taxi方法,只有在manage_tasks方法里调用task方法时,才能够传递参数,可是在这个时点,参数从哪里来???求大神指点!!!

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

c/c++ 多线程 等待一次性事件 packaged_task用法的更多相关文章

  1. c/c++ 多线程 等待一次性事件 std::promise用法

    多线程 等待一次性事件 std::promise用法 背景:不是很明白,不知道为了解决什么业务场景,感觉std::async可以优雅的搞定一切的一次等待性事件,为什么还有个std::promise. ...

  2. c/c++ 多线程 等待一次性事件 异常处理

    多线程 等待一次性事件 异常处理 背景:假设某个future在等待另一个线程结束,但是在被future等待的线程里发生了异常(throw一个异常A),这时怎么处理. 结果:假设发生了上面的场景,则在调 ...

  3. c/c++ 多线程 等待一次性事件 future概念

    多线程 等待一次性事件 future概念 背景:有时候,一个线程只等待另一个线程一次,而且需要它等待的线程的返回值. 案例:滴滴叫车时,点完了叫车按钮后,叫车的后台线程就启动了,去通知周围的出租车.这 ...

  4. c/c++ 多线程 多个线程等待同一个线程的一次性事件

    多线程 多个线程等待一个线程的一次性事件 背景:从多个线程访问同一个std::future,也就是多个线程都在等待同一个线程的结果,这时怎么处理. 办法:由于std::future只能被调用一次get ...

  5. c/c++ 多线程 一个线程等待某种事件发生

    多线程 一个线程等待某种事件发生 背景:某个线程在能够完成其任务之前可能需要等待另一个线程完成其任务. 例如:坐夜间列车,为了能够不坐过站, 1,整夜保持清醒,但是这样你就会非常累,不能够睡觉. 2, ...

  6. iOS 开发多线程篇—GCD的常见用法

    iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...

  7. iOS开发多线程篇—GCD的常见用法

    iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...

  8. c#多线程中Lock()关键字的用法小结

    本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助     本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段 ...

  9. opencv学习之等待按键事件-waitKey函数

    文章来源: https://mangoroom.cn/opencv/opencv-learning-waitKey.html 序 waitKey函数属于opencv函数里既常用又非常基础的函数,无论是 ...

随机推荐

  1. 12.Git分支-推送(push)、跟踪分支、拉取(pull)、删除远程分支

    1.推送 本地的分支并不会自动与远程仓库同步,你可以显示的向远程仓库推送你的分支.例如你在本地创建了一个dev分支,你想其他的人和你一样在dev之下进行工作,可以使用 git push <rem ...

  2. 通用网页调用本地应用程序方案(windows平台)

    一.更新注册表 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\receiveOutOfArg] "URL Protocol& ...

  3. vue组件如何被其他项目引用

    自己写的vue组件怎么才能让其他人引用呢,或者是共用组件如何让其他项目引用.本文就粗细的介绍下,如有疑问欢迎共同讨论.在这里你能了解下如下知识点: 1. 如何发布一个包到npmjs仓库上 2.如何引用 ...

  4. Python之高级特性

    一.切片 L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']取出前三个元素 , 笨方法就是通过下标一个一个获取 [L[0], L[1], L[2]]Pyt ...

  5. DDD实战进阶第一波(十五):开发一般业务的大健康行业直销系统(总结篇)

    前面我们花了14篇的文章来给大家介绍经典DDD的概念.架构和实践.这篇文章我们来做一个完整的总结,另外生成一个Api接口文档. 一.DDD解决传统的开发的几大问题: 没有描述需求的设计模型:而是直接通 ...

  6. 纽约工作日志流水账 Day 1

    周六早上8:00从青岛登机,历经17个小时,终于在当地时间周六下午2点半到达目的地纽约.         被媳妇吐槽旁边坐了美女妹子,其实是个美国妹子,旁边人家还有男朋友,全程只和我说了2句话,Exc ...

  7. 详解intellij idea搭建SSM框架(spring+maven+mybatis+mysql+junit)(下)

    在上一篇(详解intellij idea 搭建SSM框架(spring+maven+mybatis+mysql+junit)(上))博文中已经介绍了关于SSM框架的各种基础配置,(对于SSM配置不熟悉 ...

  8. 《HelloGitHub月刊》第 09 期

    <HelloGitHub>第 09 期 兴趣是最好的老师,<HelloGitHub>就是帮你找到兴趣! 前言 转眼就到年底了,月刊做到了第09期,感谢大家一路的支持和帮助

  9. 日志服务Python消费组实战(三):实时跨域监测多日志库数据

    解决问题 使用日志服务进行数据处理与传递的过程中,你是否遇到如下监测场景不能很好的解决: 特定数据上传到日志服务中需要检查数据内的异常情况,而没有现成监控工具? 需要检索数据里面的关键字,但数据没有建 ...

  10. java 虚拟机内存划分,类加载过程以及对象的初始化

    涉及关键词: 虚拟机运行时内存 java内存划分 类加载顺序  类加载时机  类加载步骤  对象初始化顺序  构造代码块顺序 构造方法 顺序 内存区域   java内存图  堆 方法区 虚拟机栈 本地 ...