• async
  • future
  • packaged_task
  • promise

async

std:async 是个函数,用来启动一个异步任务,启动起来一个异步任务之后,返回一个std::futre对象,启动一个异步任务,就是自动创建一个线程并开始执行对应的线程入口函数,它返回一个std::future对象,这个std::future对象里面就含有线程入口函数返回的结果。可以通过调用future对象的成员函数get来获取结果。

"future" 提供了一种访问异步操作结果的机制,程序运行的结果,可能没有办法马上拿到。可能需要一定时间才能返回结果。在线程执行完毕的时候,就能够拿到结果。所以大家这么理解,future里会保存一个值。

例子:

引入一个头文件

#include<future>

 需要执行的函数,线程入口函数

int mythread()
{
cout << "my thread start, and thread id is " << std::this_thread::get_id() <<endl;
std::chrono::milliseconds dura(500);
std::this_thread::sleep_for(dura);
cout << "my thread end, and thread id is " << std::this_thread::get_id() <<endl; return 5; }

  在main中:

	cout << "Main Thread End!!! " <<std::this_thread::get_id() <<endl;

	std::future<int> result = std::async(mythread);

	cout << "continue..." << endl;

	int def = 0;
def = 0;
cout << result.get() << endl;
cout << "Main thread end" << endl;

  当执行到get的时候,系统会卡在这里,一直等待线程执行完毕。线程执行完毕之后,返回。future里有个标记,标记当前的线程已经执行完毕,流程才能继续往下走。绑定关系,future和async创建的线程绑定到一起,一定要等待线程执行完了,程序才能往下执行。

future

get函数不拿到 future的返回值,就卡在这里等待拿值,必须要保证和future有关的函数一定要有返回值。

future中还有一个wait(),等待线程返回,本身并不返回结果。 join();

程序中如果同时写多个get函数,那么就会报错,get只能调用一次!

在std::thread 用类的成员函数来作为线程的入口函数,用async也能用类的成员函数来作为线程的入口函数。

std::future<int> result = std::async(&class::method, &obj, para1)

 从第三个参数开始,才是成员函数对应的参数。第二个参数是一个对象引用,才能保证线程里面用的是同一个对象,线程里面当执行函数的时候仍然对应的是那个对象。

std::future<int> result = std::async(std::launch::deferred, &class::method, &obj, para1);

std::future<int> result = std::async(std::launch::async, &class::method, &obj, para1);

  

如果新建了future对象之后,不用get()和wait(),线程依然会运行,线程运行结束后,程序退出。

get()成员函数等待线程执行结束后返回结果,我们通过额外向std::async()传递一个参数,该参数类型是std::launch类型(枚举类型)来达到一些特殊的目的。

a)std::launch::deferred:表示线程入口函数调用被延迟到std::future的wait()或者get()函数调用时才执行。实际上线程根本没有被创建。

b) std::launch::async,在调用的时候就开始创建线程,不会等到get().

两个标记不能一起使用,用的时候必须要搞明白这些标记的含义。

packaged_task

std::packaged_task:打包任务,或者说将任务包装起来,这也是一个类模板。模板参数是各种可调用参数,通过packaged_task可以把各种可调用对象包装起来,方便将来作为线程入口函数作为调用。

在main函数中,相当于包装了一个函数,<int(int)> 返回值(参数),实参就是入口函数,可调用对象。我们

std::packaged_task<int(int)>  mypt(mythread);

把函数mythread通过如下写法调用:

std::thread t1(std::ref(mypt), 1);

 只不过线程创建方法是包装起来的线程入口函数,线程直接开始执行,第二个参数1,作为线程入口函数的参数,作为mythread的入口参数。通过future取结果

std::future<int> result = mypt.get_future();

  只要绑定之后,future里面保存的就是mypt里面的值。std::future对象里包含有线程入口函数的返回结果,这里result保存mythread。

packaged_task 包装起来的可调用对象还可以直接调用。

promise

std::promise这个也是一个类模板,作用是能够在某个线程中给它赋值,然后把这个值取出来。在线程中进行一个很复杂的运算,然后拿到运算结果。

void mythread(std::promise<int> &tmp, int calc);

  可以在函数中做一系列复杂的操作,然后做其他运算,整整花费了5s,休息了一定时间,结果可以保存下来,然后

int result = calc;
tmp.set_value(result); //将结果保存并返回

  结果保存到了tmp这个对象中,在main中声明一个std::promise对象,可以保存这个值,保存的值为int类型

std::promise<int> myprom;
std::thread t1(mythread, std::ref(myprom), para); //然后等线程执行完
t1.join();

  获取结果可以用到其他线程中去。

std::future<int> fu1 = myprom.get_future(); //promise和future绑定用于获取线程返回值

  如果前面join了后面get能够马上拿到这个值。

auto result = fu1.get();

  

C++并发与多线程学习笔记--async、future、packaged_task、promise的更多相关文章

  1. C++并发与多线程学习笔记--future成员函数、shared_future、atomic

    std::future的其他成员函数 std::shared_future 原子操作.概念.基本用法 多线程主要是为了执行某个函数,本文的函数的例子,采用如下写法 int mythread() { c ...

  2. C++并发与多线程学习笔记--atomic

    std::atomic std::async std::atomic 一般atomic原子操作,针对++,--,+=,^=是支持的,其他结果可能不支持. 注意 std::atomic<int&g ...

  3. C++并发与多线程学习笔记--基本概念和实现

    基本概念 并发 可执行程序.进程.线程 学习心得 并发的实现方法 多进程并发 多线程并发 总结 C++标准库 基本概念 (并发.进程.线程)区分C++初级编程和中高级编程 并发 两个或者更多的任务同时 ...

  4. C++并发与多线程学习笔记--互斥量、用法、死锁概念

    互斥量(mutex)的基本概念 互斥量的用法 lock(), unlock() std::lock_guard类模板 死锁 死锁演示 死锁的一般解决方案 std::lock()函数模板 std::lo ...

  5. C++并发与多线程学习笔记--单例设计模式、共享数据分析

    设计模式 共享数据分析 call_once 设计模式 开发程序中的一些特殊写法,这些写法和常规写法不一样,但是程序灵活,维护起来方便,别人接管起来,阅读代码的时候都会很痛苦.用设计模式理念写出来的代码 ...

  6. C++并发与多线程学习笔记--多线程数据共享问题

    创建和等待多个线程 数据和共享问题分析 只读的数据 有读有写 其他案例 共享数据的保护案例代码 创建和等待多个线程 服务端后台开发就需要多个线程执行不同的任务.不同的线程执行不同任务,并返回执行结果. ...

  7. C++并发与多线程学习笔记--参数传递详解

    传递临时对象 陷阱 总结 临时对象作为线程参数 线程id的概念 临时对象构造时的抓捕 成员函数指针做线程函数 传递临时对象作为线程参数 创建的工作线程不止一个,线程根据编号来确定工作内容.每个线程都需 ...

  8. C++并发与多线程学习笔记--线程之间调度

    condition_variable wait() notify_one notify_all condition_variable 条件变量的实际用途: 比如有两个线程A和B,在线程A中等待一个条件 ...

  9. C++并发与多线程学习笔记--unique_lock详解

    unique_lock 取代lock_quard unique_lock 的第二个参数 std::adopt_lock std::try_to_lock std::defer_lock unique_ ...

随机推荐

  1. UML online tools

    UML online tools UML https://www.diagrams.net/assets/svg/home-dia1.svg refs https://www.diagrams.net ...

  2. text image & 思维脑图 & xmind

    text image & 思维脑图 text-image 图片读 rgb 值->灰度值->字符; rgb->灰度值的公式 google 一下就有,灰度值传字符部分,从灰度值从 ...

  3. Mila Fletcher:日常理财应注意的五点

    米拉·弗莱彻于2007年毕业于耶鲁大学,她是一名真正意义上的法学博士,在校期间获得了马歇尔奖学金,毕业后曾在美国多家知名律师事务所任职,目前就职于星盟全球投资公司,专注于帮助公司和客户提供法务咨询,他 ...

  4. 1. VUE介绍

    今天开始系统学习vue前端框架. 我是有前端基础的, 刚工作那会, 哪里分那么清楚啊, 前后端我都得做, 所以, css, js, jquery, bootstrap都会点, 还系统学过ext, 哈哈 ...

  5. 云原生系列6 基于springcloud架构风格的本地debug实现

    debug是程序员在日常开发中最常使用的操作, 那么,你是如何快速在微服务架构风格下快速debug后端服务呢? 开发现状 开发的理想状态 本地调测的使用步骤 登录智能网关 如果集成开发环境是在本地局域 ...

  6. 哪些原因会导致JAVA进程退出?

    本文转载自哪些原因会导致JAVA进程退出? 导语 JAVA进程消失可能有哪些原因? 那我们就开一篇文章说一下这个问题,其实很easy的,无外乎三种情况. linux的OOM killer杀死 JVM自 ...

  7. Dockerfile多阶段构建原理和使用场景

    本文转载自Dockerfile多阶段构建原理和使用场景 导语 Docker 17.05版本以后,新增了Dockerfile多阶段构建.所谓多阶段构建,实际上是允许一个Dockerfile 中出现多个 ...

  8. Java自学第10期——File类与IO流(输入输出流、处理流、转换流、缓冲流、Properties集合、打印流)

    1.IO简介 IO(输入输出)通过java.io包下的类和接口来支持,包下包括输入.输出两种IO流,每种输入输出流又可分为字符流和字节流两大类. 2.File类 File类是io包下与平台无关的文件和 ...

  9. 一个基于 Vue3 的开源项目,3个月时间 star 终于破千!

    本文主要是对如何做开源项目的一些思考. 前文回顾: <Vue3 来了,Vue3 开源商城项目重构计划正式启动!> <一个基于 Vue 3 + Vant 3 的开源商城项目> 关 ...

  10. 模式识别Pattern Recognition

    双目摄像头,单目摄像头缺少深度 Train->test->train->test->predicive