C++线程学习七(异步)

1、async和future的使用

 

(1)std::async   std::future创建后台任务并返回

【1】std::async
        std::async是一个函数模板,用来启动一个异步任务,启动起来就是一个已步入任务后,返回一个std::future 对象,std::future是一个类模板
        “启动一个异步任务”,就是创建一个线程并执行对应线程的入口函数,返回一个std::future对象
        std::future对象内含有线程入口函数所返回的结果(线程返回结果)。我们可以通过调用对象的成员函数get()类获取结果
        std::future提供一种访问异步操作结果的机制,就是说你不能立马拿到结果,需要等待线程结束的时候,你就能拿到结果
【2】std::packaged_task: 打包任务
         是一个类模板,他的模板参数是各种可调用对象,通过std::packaged_task把各种可调用对象包装起来,方便将来作为线程入口;
        packaged_task包装起来的可调用对象还可以直接调用
【3】std::promise,类模板
        在某个线程中给他赋值,然后在其他的线程中,把这个值取出来

示例一:std::async 与 std::future的使用

// 程序通过std::future对象的get()成员函数,等待线程执行结束并返回结果,没拿到返回值,程序不会往下运行
// wait()成员函数等待线程返回,不返回结果
std::future<int> res = std::async(ThreadIO, 2);    // 创建一个线程开始执行
cout << "continue ... " << endl;
int def = 0;
cout << res.get() << endl;            // 卡在这里等待threasIO执行完
// res.wait();                        //不会有返回值
cout << "end" << endl;

(2)std::async()的其他参数

通过std::async()传递一个参数,此参数类型是std::lunnch(枚举类型),来实现其他的函数功能
【1】std::launch::deferred:表示线程入口函数调用被延迟到std::future的wait()或者get()函数调用时才执行
          如果wait()或者get()没有被调用,线程不会被创建,所以线程不会执行
【2】std::launch::async,在调用async函数的时候就开始创建线程
          std::async()函数默认的就是std::launch::async参数

示例二:std::lunnch使用用例

threadIO thIO;
int tmppar = 12;
cout << "main thread ID " << this_thread::get_id() << endl;
std::future<int> res = std::async(&threadIO::ThreadIO, &thIO, tmppar);  // 正常使用
//std::future<int> res = std::async(std::launch::deferred, &threadIO::ThreadIO, &thIO, tmppar);  
//std::future<int> res = std::async(std::launch::async, &threadIO::ThreadIO, &thIO, tmppar);    
cout << "continue ... " << endl;
int def = 0;
cout << res.get() << endl;                       // 卡在这里等待threasIO执行完
// res.wait();

(3)打包函数

packaged_task使用用例

cout << "main thread ID " << this_thread::get_id() << endl;
std::packaged_task<int(int)> mypt(ThreadIO);
std::thread t1(std::ref(mypt), 1);		// 创建线程,线程直接开始执行,第二份参数作为线程入口函数的参数
t1.join();
std::future<int> res = mypt.get_future();  // 获取线程返回值,std::future对象里包含有线程入口函数的返回结果
cout << res.get() << endl;
cout << "end" << endl;

打包lumda表达式

std::packaged_task<int(int)> mypt([](int num) {
cout << "input thread param " << num << endl;
cout << "start this  thread ID " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
cout << "end this  thread ID " << std::this_thread::get_id() << endl;
return 5;
});

代码示例

#include <iostream>	
#include <thread>
#include <mutex>
#include <future>
#include <vector>
using namespace std;
int ThreadIO(int num)
{
  cout << "input thread param " << num << endl;
  cout << "start this  thread ID " << std::this_thread::get_id() << endl;
  std::chrono::milliseconds dura(5000);
  std::this_thread::sleep_for(dura);
  cout << "end this  thread ID " << std::this_thread::get_id() << endl;
  return 5;
}


void promiseThread(std::promise<int> &temp, int num)
{
  num += 10;
  int res = num;
  temp.set_value(res);  // 将结果保存到temp对象中
}

void proThread(std::future<int> &temp)
{
  auto res = temp.get();
  cout << "proThread res: " << res << endl;
  return;
}



int main()
{
  /*     //  示例一  :打包函数
  cout << "main thread ID " << this_thread::get_id() << endl;
  std::packaged_task<int(int)> mypt(ThreadIO);
  std::thread t1(std::ref(mypt), 1);			// 创建线程,线程直接开始执行,第二份参数作为线程入口函数的参数
  t1.join();
  std::future<int> res = mypt.get_future();   // 获取线程返回值,std::future对象里包含有线程入口函数的返回结果
  cout << res.get() << endl;
  cout << "end" << endl;
  */
  //  示例二 : 打包lumda表达式
  std::packaged_task<int(int)> mypt([](int num) {
    cout << "input thread param " << num << endl;
    cout << "start this  thread ID " << std::this_thread::get_id() << endl;
    std::chrono::milliseconds dura(5000);
    std::this_thread::sleep_for(dura);
    cout << "end this  thread ID " << std::this_thread::get_id() << endl;
    return 5;
    });
#if 0   // 容器的用法
  std::vector<packaged_task<int(int)>> vProj;
  vProj.push_back(std::move(mypt));
  std::packaged_task<int(int)> mypt2;
  auto it = vProj.begin();
  mypt2 = std::move(*it);   // 移动语义
  vProj.erase(it);         // 删除第一个元素,后续不能使用it
  mypt2(520);
  std::future<int> res1 = mypt2.get_future();   // 获取线程返回值,std::future对象里包含有线程入口函数的返回结果
  cout << res1.get() << endl;
  cout << "end" << endl;
#endif
  std::promise<int> tPromise; // 声明promise对象,保存类型为int
  std::thread t(promiseThread, std::ref(tPromise), 180);
  t.join();
  // 获取结果
  std::future<int> ful = tPromise.get_future();   // 拿到上一个线程的值
  //auto res = ful.get();							
  //cout << res << endl;
  std::thread t1(proThread, std::ref(ful));		// get()不能重复调用,在proThread()函数中有调用,所以上面需要注释掉
  t1.join();
  cout << "end" << endl;
  system("pause");
  return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值