多线程 等待一次性事件 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

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. HBase之CF持久化系列(续1)

    这一节本来打算讲解HRegion的初始化过程中一些比较复杂的流程.不过,考虑前面的博文做的铺垫并不够,因此,在这一节,我还是特意来介绍HBase的CF持久化.关于这个话题的整体流程性分析在博文< ...

  2. MySQL优化之my.conf配置详解

    最近项目不太忙,所以有时间静心来研究下mysql的优化,对于MySQL的设置是否合理优化,直接影响到网站的速度和承载量!同时,MySQL也是优化难度最大的一个部分,不但需要理解一些MySQL专业知识, ...

  3. Java IO流读取文件

    使用指定编码读取文件 public static String toString(File file, String charset){ StringBuilder result = new Stri ...

  4. [Abp 源码分析]八、缓存管理

    0.简介 缓存在一个业务系统中十分重要,常用的场景就是用来储存调用频率较高的数据.Abp 也提供了一套缓存机制供用户使用,在使用 Abp 框架的时候可以通过注入 ICacheManager 来新建/设 ...

  5. scala中spark运行内存不足

    用 bash spark-submit 在spark上跑代码的时候出现错误: ERROR executor.Executor: Exception in task 9.0 in stage 416.0 ...

  6. 分享几个 SpringBoot 实用的小技巧

    前言 最近分享的一些源码.框架设计的东西.我发现大家热情不是特别高,想想大多数应该还是正儿八经写代码的居多:这次就分享一点接地气的: SpringBoot 使用中的一些小技巧. 算不上多高大上的东西, ...

  7. CentOs~程序部署那些事

    永久更新中…… 主要说一下在centos里,在安装程序和监控程序时,用到的一些常用的命令,希望可以帮到大家! 远程安装程序包:yum install 程序包名 下载程序包:wget 程序包地址 解压t ...

  8. 基础才是重中之重~delegate里的Invoke和BeginInvoke

    回到目录 Invoke和BeginInvoke都是调用委托实体的方法,前者是同步调用,即它运行在主线程上,当Invode处理时间长时,会出现阻塞的情况,而BeginInvod是异步操作,它会从新开启一 ...

  9. .NET快速信息化系统开发框架 V3.2 -> WinForm“组织机构管理”界面组织机构权限管理采用新的界面,操作权限按模块进行展示

    对于某些大型的企业.信息系统,涉及的组织机构较多,模块多.操作权限也多,对用户或角色一一设置模块.操作权限等比较繁琐.我们可以直接对某一组织机构进行权限的设置,这样设置后,同一组织机构的用户就可以拥有 ...

  10. 从设计模式的角度看Java程序优化

    一.前言 Java程序优化有很多种渠道,比如jvm优化.数据库优化等等,但都是亡羊补牢的措施,如果能在设计程序架构时利用设计模式就把程序的短板解决,就能使程序更加健壮切容易维护迭代 二.常用的设计模式 ...