• 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();

  

最新文章

  1. HTML常用属性
  2. [Spring MVC] - 从数据库读取MessageSource
  3. ubuntu mysql远程登录设置
  4. ubuntu修改源列表sourcelist的方法
  5. 我的MYSQL学习心得(十一)
  6. c标签和foreach循环不能加载
  7. jstl标签库示例二
  8. node.js 的url模块
  9. 美国5G:初步上线玩砸,信号难寻和4G无差别
  10. MySQL 聚合函数 控制流程函数
  11. Python笔记记录
  12. 数据库解析IP,时间戳
  13. MySQL Workbench在archlinux中出现 Could not store password: The name org.freedesktop.secrets was not provided by any .service files的错误
  14. angular 我看过的技术书籍
  15. Eclipse快捷键系列
  16. CTF-练习平台-Misc之 多种方法解决
  17. Spring MVC 学习笔记2 - 利用Spring Tool Suite创建一个web 项目
  18. JAVA读取XML,JAVA读取XML文档,JAVA解析XML文档,JAVA与XML,XML文档解析(Document Object Model, DOM)
  19. 【软件位置】Linux查看软件安装的位置
  20. Map集合统计字母次数

热门文章

  1. MongoDB 101
  2. css infinite loop animation
  3. egg.js 如何禁用 sensors data
  4. alipay 小程序开发教程
  5. git merge all in one
  6. 「NGK每日快讯」2021.1.22日NGK公链第80期官方快讯!
  7. lms微服务框架介绍
  8. [转]Linux 线程实现机制分析 Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL
  9. 生成类库项目时同时生成的pdb文件是什么东东?
  10. c#(winform)获取本地打印机