经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
c/c++ 多线程 等待一次性事件 packaged_task用法
来源:cnblogs  作者:小石王  时间:2018/11/25 20:04:47  对本文有异议

多线程 等待一次性事件 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::move转成右值,否则编译不过。把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::move(task1), 100);
  4. t1.detach();//task1(100)是异步执行,也就是在新的线程里执行。
  5. std::cout << "111111111111111111111111111111" << std::endl;

4,std::packaged_task的拷贝构造函数是被删除了的,所以std::packaged_task作为函数的参数时,必须用std::move(task),把它转成右值引用。

代码:

  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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号