文章目录
前言
语言:c++11
(1)std:packaged_task:通过std::packaged_task 来把各种可调用对象包装起来,方便将来作为线程入口函数来调用
。;
(2)std::promise:我们能够在某个线程中给它赋值,然后我们可以在其他线程中,把这个取值出来用。
(3)代码案例。
一、std::packaged_task
1.1 函数介绍
std::packaged_task:打包任务,把任务包装起来。
(1)是个类模板,它的模板参数是 各种可调用对象;通过std::packaged_task 来把各种可调用对象包装起来,方便将来作为线程入口函数来调用
。
(2)packaged_task包装起来的可调用对象还可以直接调用
,所以从这个角度来讲,packaged_task对象,也是 一个可调用对象;
1.2 使用步骤
1.2.1 代码案例1
包装起来的可调用对象,作为函数入口函数来调用。
代码实例:
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <SDKDDKVer.h>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <list>
#include <mutex>
#include <future>
int mythread1(int mypar) //线程入口函数
{
cout << "mythrea() start" << " threadid = " << std::this_thread::get_id() << endl; //打印新线程id
std::chrono::milliseconds dura(5000); //订一个5秒的时间
std::this_thread::sleep_for(dura); //休息了一定时长
cout << "mythread() end" << " threadid = " << std::this_thread::get_id() << endl; //打印新线程id
return 5;
}
int main()
{
//二:std::packaged_task:打包任务,把任务包装起来
//是个类模板,它的模板参数是 各种可调用对象;通过std::packaged_task 来把各种可调用对象包装起来,方便将来作为线程入口函数来调用;
cout << "main" << " threadid = " << std::this_thread::get_id() << endl;
std::packaged_task<int(int)> mypt(mythread1);
//我们把函数mythread通过packaged_task包装起来
std::thread t1(std::ref(mypt), 1);
//线程直接开始执行,第二个参数 作为线程入口函数的参数。
t1.join();
//等待线程执行完毕。
std::future<int> result = mypt.get_future();
//std::future对象里包含有线程入口函数的返回结果,这里result保存mythread返回的结果。
cout << result.get() << endl;
cout << "I Love China!" << endl;
return 0;
}
运行截图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/1131216c5b8842e9aedf0db9a4e806e9.png)
1.2.2 代码案例2
包装起来的可调用对象,直接被调用。
代码如下(示例):
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <SDKDDKVer.h>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <list>
#include <mutex>
#include <future>
int mythread1(int mypar) //线程入口函数
{
cout << "mythrea() start" << " threadid = " << std::this_thread::get_id() << endl; //打印新线程id
std::chrono::milliseconds dura(5000); //订一个5秒的时间
std::this_thread::sleep_for(dura); //休息了一定时长
cout << "mythread() end" << " threadid = " << std::this_thread::get_id() << endl; //打印新线程id
return 5;
}
int main()
{
//packaged_task包装起来的可调用对象还可以直接调用,所以从这个角度来讲,packaged_task对象,也是 一个可调用对象;
cout << "main" << " threadid = " << std::this_thread::get_id() << endl;
std::packaged_task<int(int)> mypt([](int mypar) {
cout << mypar << endl;
cout << "mythread() start" << " threadid = " << std::this_thread::get_id() << endl;
//打印新线程id
std::chrono::milliseconds dura(5000);
//订一个5秒的时间
std::this_thread::sleep_for(dura);
//休息了一定时长
cout << "mythread() end" << " threadid = " << std::this_thread::get_id() << endl;
//打印新线程id
return 5;
});
//std::thread t1(sed::ref(mypt), 1);
//线程直接开始执行,第二个参数 作为线程入口函数的参数。
//t1.join();
//等待线程执行完毕。
//std::future<int> result = mypt.get_future();
//std::future对象里包含有线程入口函数的返回结果,这里result保存mythread返回的结果。
//cout << result.get() << endl;
//cout << "I Love China!" << endl;
mypt(105);
//直接调用,相当于函数调用;
std::future<int> result = mypt.get_future();
cout << result.get() << endl;
return 0;
}
运行截图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/a7dc2f80fca64909982fc3adb1645c7b.png)
二、std::promise
2.1 基本介绍
- std::promise,类模板
- 我们能够在某个线程中给它赋值,然后我们可以在其他线程中,把这个取值出来用;
总结:通过promise保存一个值,在将来某个时刻我们通过把一个future绑定到这个promise上来得到这个绑定的值;
2.2 使用步骤
2.2.1 代码案例
void mythread2(std::promise<int> &tmpp, int calc) //大家注意第一个参数
{
//做一系列复杂的操作
calc++;
calc *= 10;
//做其他运行,比如整整花费了5秒钟;
std::chrono::milliseconds dura(5000);
//订一个5秒的时间
std::this_thread::sleep_for(dura);
//休息了一定时长
//终于计算出结果了
int result = calc;
//保存结果
tmpp.set_value(result);
//结果我保存到了tmpp这个对象中;
return;
}
void mythread3(std::future<int> &tmpf)
{
auto result = tmpf.get();
cout << "mythread2 result = " << result << endl;
return;
}
int main()
{
//三:std::promise,类模板
//我们能够在某个线程中给它赋值,然后我们可以在其他线程中,把这个取值出来用;
//总结:通过promise保存一个值,在将来某个时刻我们通过把一个future绑定到这个promise上来得到这个绑定的值;
std::promise<int> myprom;
//声明一个std::promise对象myprom,保存的值类型为int;
std::thread t1(mythread2, std::ref(myprom), 4);
t1.join();
//获取结果值
std::future<int> ful = myprom.get_future();
//promise和future绑定,用于获取线程返回值
//auto result = ful.get();
//get只能调用一次,不能调用多次
//cout << "result = " << result << endl;
std::thread t2(mythread3, std::ref(ful));
t2.join();
//等mythread2线程执行完毕
cout << "end!" << endl;
//四:小结:到底怎么用,什么时候用;
//我们学习这些东西的目的,并不是要把他们都用在咱们自己的实际开发中。
//相反,如果我们能够用最少的东西能够写出一个稳定、高效地多线程程序,更值得赞赏;
//我们为了成长,必须要要阅读一些高手写的代码,从而快速实现自己代码的积累,我们的技术就会有一个大幅度的提升;
//老师更愿意将学习这些内容的理由解释为:为我们将来能够读懂高手甚至大师写的代码而铺路;
return 0;
}
运行截图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/ed03c761968543feb29ade6cf748dfce.png)
总结
(1)了解std::packaged_task的基本使用;
(2)了解两种调用方式:作为函数接口被调用和直接调用。