C++并行开发9-async、future、packaged_task、promise
std::future 使用
小试牛刀
一、 std::async、std::future创建后台任务并返回值 希望线程返回一个结果
std::async是一个函数模板,用来启动一个异步任务,启动一个异步任务之后,他返回一个future对象 什么是“启动一个异步任务”,
自动创建一个线程,并且开始执行对应的线程入口函数,他返回一个std::future对象。
这个std::future对象中就含有线程入口函数所返回的结果,我们可以通过调用future对象的成员函数get()来获取
std::future,通俗一点就是future中会保存一个值,将来可以拿到 需要注意的是get()函数方法只能使用一次
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <list>
#include <mutex>
#include <future> //引入std::future头文件
using namespace std;
int my_thread() { //线程入口函数
cout << "mythread start" << " threadid is = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000); //休息了5s
std::this_thread::sleep_for(dura);
cout << "over " << endl;
return 5;
}
int main() {
// 一、 std::async、std::future创建后台任务并返回值
// 希望线程返回一个结果
// std::async是一个函数模板,用来启动一个异步任务,启动一个异步任务之后,他返回一个future对象
// 什么是“启动一个异步任务”, 自动创建一个线程,并且开始执行对应的线程入口函数,他返回一个std::future对象。
// 这个std::future对象中就含有线程入口函数所返回的结果,我们可以通过调用future对象的成员函数get()来获取
// std::future,通俗一点就是future中会保存一个值,将来可以拿到
cout << "main " << " threadid is = " << std::this_thread::get_id() << endl;
std::future<int> result = std::async(my_thread); //async:异步;
cout << "continue " << endl;
cout << result.get() << endl; //卡到这里一直到mythread执行完毕 只能调用一次
cout << "主函数运行结束" << endl;
return 0;
}
调用类成员函数,并且使用std::launch
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <list>
#include <mutex>
#include <future> //引入std::future头文件
using namespace std;
class A {
public:
int my_thread(int mypar) { //线程入口函数
cout << mypar << endl;
cout << "mythread start" << " threadid is = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000); //休息了5s
std::this_thread::sleep_for(dura);
cout << "over " << endl;
return 5;
}
};
int main() {
// 一、 std::async、std::future创建后台任务并返回值
// 希望线程返回一个结果
// std::async是一个函数模板,用来启动一个异步任务,启动一个异步任务之后,他返回一个future对象
// 什么是“启动一个异步任务”, 自动创建一个线程,并且开始执行对应的线程入口函数,他返回一个std::future对象。
// 这个std::future对象中就含有线程入口函数所返回的结果,我们可以通过调用future对象的成员函数get()来获取
// std::future,通俗一点就是future中会保存一个值,将来可以拿到
//我们可以向std::async传递std::launch(枚举类型)
// a) std::launch::deferred表示线程入口函数被延迟到std::future的wait()或者get()函数调用时才执行,此时线程都没有创建
// 并且实际上std::launch::deferred就没有创建新线程,是在主线程中调用的线程入口函数
// b) std::launch::async调用了新线程,是默认使用的参数
A a;
cout << "main " << " threadid is = " << std::this_thread::get_id() << endl;
//std::future<int> result = std::async(my_thread); //async:异步;
std::future<int> result = std::async(std::launch::deferred, &A::my_thread, a, 100); //async:异步;
cout << "continue " << endl;
cout << result.get() << endl; //卡到这里一直到mythread执行完毕 只能调用一次
cout << "主函数运行结束" << endl;
return 0;
}
std::launch 有async,和deferred
async会重新创建一个新的线程,但是deferred不会重新重建一个新的线程,只当函数运行到get或者wait的时候才会被执行;
使用std::packaged_task
二、packaged_task: 打包任务,把任务打包起来
是个类模板,他的模板参数是各种可以调用对象,通过std::packaged_task来把各种调用对象包装起来,方便作为线程入口函数
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <list>
#include <mutex>
#include <future> //引入std::future头文件
using namespace std;
class A {
public:
int my_thread(int mypar) { //线程入口函数
cout << mypar << endl;
cout << "mythread start" << " threadid is = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000); //休息了5s
std::this_thread::sleep_for(dura);
cout << "over " << endl;
return 5;
}
};
int my_thread(int mypar) { //线程入口函数
cout << mypar << endl;
cout << "mythread start" << " threadid is = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000); //休息了5s
std::this_thread::sleep_for(dura);
cout << "over " << endl;
return 5;
}
int main() {
// 二、std::packaged_task: 打包任务,把任务打包起来
// 是个类模板,他的模板参数是各种可以调用对象,通过std::packaged_task来把各种调用对象包装起来,方便作为线程入口函数
cout << "main " << " threadid is = " << std::this_thread::get_id() << endl;
std::packaged_task<int(int)> mypt(my_thread);
std::thread t1(std::ref(mypt), 1);
t1.join();
std::future<int> result = mypt.get_future(); //rsult保存my_thread的结果
cout << result.get();
cout << "主线程运行结束" << endl;
}
也可以使用lambda代替
int main() {
cout << "main " << " threadid is = " << std::this_thread::get_id() << endl;
/*std::packaged_task<int(int)> mypt(my_thread);*/
//使用lambda表达式
std::packaged_task<int(int)> mypt([](int mypar) {
cout << mypar << endl;
cout << "mythread start" << " threadid is = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000); //休息了5s
std::this_thread::sleep_for(dura);
cout << "over " << endl;
return 5;
});
std::thread t1(std::ref(mypt), 1);
t1.join();
std::future<int> result = mypt.get_future(); //rsult保存my_thread的结果
cout << result.get();
cout << "主线程运行结束" << endl;
}
packaged_task也可以在main函数中直接使用
std::packaged_task<int(int)> mypt([](int mypar) {
cout << mypar << endl;
cout << "mythread start" << " threadid is = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000); //休息了5s
std::this_thread::sleep_for(dura);
cout << "over " << endl;
return 5;
});
//std::thread t1(std::ref(mypt), 1);
//t1.join();
mypt(100);
std::future<int> result = mypt.get_future(); //rsult保存my_thread的结果
cout << result.get();
在容器中使用std::packaged_task
std::vector<std::packaged_task<int(int)>> mytask;
int main() {
cout << "main " << " threadid is = " << std::this_thread::get_id() << endl;
std::packaged_task<int(int)> mypt([](int mypar) {
cout << mypar << endl;
cout << "mythread start" << " threadid is = " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000); //休息了5s
std::this_thread::sleep_for(dura);
cout << "over " << endl;
return 5;
});
mytask.push_back(std::move(mypt));
std::packaged_task<int(int)> mypt2;
auto iter = mytask.begin();
mypt2 = std::move(*iter);
//mypt2 = std::move(*iter);
mytask.erase(iter);
mypt2(123);
std::future<int> result = mypt2.get_future(); //rsult保存my_thread的结果
cout << result.get();
cout << "主线程运行结束" << endl;
return 0;
}
使用std::promise
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <list>
#include <mutex>
#include <future> //引入std::future头文件
using namespace std;
// 三、 std::promise, 类模板
// 我们能够在某个线程中给它赋值,然后再在其他线程中把这个值取出来
void mythread(std::promise<int>& temp, int calc) {
// 做一些运算
calc++;
calc *= 10;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
int result = calc;
temp.set_value(result); //结果已经保存到了temp中
}
int main()
{
std::promise<int> myprom;
std::thread t1(mythread, std::ref(myprom), 180);
t1.join();
//获取结果
std::future<int> fu1 = myprom.get_future(); //promise 和 future绑定,用于获取线程返回值
auto result = fu1.get();
cout << "result = " << result << endl;
cout << "主线程结束 " << endl;
}
两个类型之间的传递
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <list>
#include <mutex>
#include <future> //引入std::future头文件
using namespace std;
// 三、 std::promise, 类模板
// 我们能够在某个线程中给它赋值,然后再在其他线程中把这个值取出来
void mythread(std::promise<int>& temp, int calc) {
// 做一些运算
calc++;
calc *= 10;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
int result = calc;
temp.set_value(result); //结果已经保存到了temp中
}
void mythread2(std::future<int>& temp) {
auto result = temp.get();
cout << "mythread2 result is" << result << endl;
}
int main()
{
std::promise<int> myprom;
std::thread t1(mythread, std::ref(myprom), 180);
t1.join();
//获取结果
std::future<int> fu1 = myprom.get_future(); //promise 和 future绑定,用于获取线程返回值
//auto result = fu1.get();
std::thread t2(mythread2, std::ref(fu1));
t2.join();
cout << "主线程结束 " << endl;
}
小结
- Title: C++并行开发9-async、future、packaged_task、promise
- Author: FengLY
- Created at : 2023-06-18 22:40:09
- Updated at : 2023-06-18 22:58:11
- Link: https://zhouaq.com/2023/06/18/C++并行开发9-async、future、packaged_task、promise/
- License: This work is licensed under CC BY-NC-SA 4.0.
Comments