c/c++语言开发共享c/c++ 多线程 等待一次性事件 packaged_task用法

多线程 等待一次性事件 packaged_task用法 背景:不是很明白,不知道为了解决什么业务场景,感觉std::asynck可以优雅的搞定一切,一次等待性事件,为什么还有个packaged_task。 用法:和std::async一样,也能够返回std::future,通过调用get_futur …


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

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

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

特点:

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

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

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

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

3,作为线程的参数时,必须用std::move转成右值,否则编译不过。把task放在线程里后,就是异步执行了。

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

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

代码:

#include <deque> #include <mutex> #include <future> #include <thread> #include <iostream> #include <unistd.h> #include <string> //#include <utility>  std::mutex mut; std::deque<std::packaged_task<std::string(int)>> tasks;  void manage_tasks(){   while(true){     sleep(1);     //std::cout << "please wait for a moument" << std::endl;     std::packaged_task<std::string(int)> task;     {       std::lock_guard<std::mutex> lg(mut);       if(tasks.empty()) continue;       std::cout << "----------------------not empty---------------" << std::endl;       task = std::move(tasks.front());       tasks.pop_front();     }     task(1);     //std::string s = task(10);   } }  template<typename call> std::future<std::string> add_task(call ca){   std::cout << "----------------------add_task---------------" << std::endl;     std::packaged_task<std::string(int)> task(ca);   std::future<std::string> ret = task.get_future();   std::lock_guard<std::mutex> lg(mut);   tasks.push_back(std::move(task));   return ret; }  std::string call_texi(int i = 0){   std::cout << "-------------jiaoche---------------" << std::endl;   if(i == 1){     return "aaa";   }else{     return "bbb";   } }  std::string call_zhuanche(int i){   std::cout << "zhuanche:" << i << std::endl;   return std::to_string(i); } int main(){      std::thread background_thread(manage_tasks);   background_thread.detach();    std::future<std::string> fut1 = add_task(call_texi);   std::cout << fut1.get() << std::endl;      std::future<std::string> fut2 = add_task(call_zhuanche);   std::cout << fut2.get() << std::endl;    pthread_exit(null);  } 

编译方法:

g++ -g xxx.cpp -std=c++11 -pthread

运行结果:

----------------------add_task--------------- ----------------------not empty--------------- -------------jiaoche--------------- aaa ----------------------add_task--------------- ----------------------not empty--------------- zhuanche:1 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

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

本人微信:xiaoshitou5854

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/606184.html

(0)
上一篇 2021年5月13日
下一篇 2021年5月13日

精彩推荐