zoukankan      html  css  js  c++  java
  • c/c++ 多线程 等待一次性事件 packaged_task用法

    多线程 等待一次性事件 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::ref。把task放在线程里后,就是异步执行了。

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

    代码:

    #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);
    
    }
    
    

    github源代码

    编译方法:

    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

    本人微信:xiaoshitou5854

  • 相关阅读:
    python 合并 Excel 单元格
    python 设置 Excel 表格的行高和列宽
    Python 用 openpyxl 模块统计 Excel 表格中的数据,以字典形式写入 py 文件
    python 打印字母阶梯和金字塔
    python 用 openpyxl 读取 Excel 表格中指定的行或列
    Python 的 filter() 函数
    Python 的 map() 函数
    python 之 range() 函数
    python 的 reduce() 函数
    python 之 lambda 函数
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/10014219.html
Copyright © 2011-2022 走看看