9.异步并发—— async future packaged_task promise

1. async 、 future

是C++11引入的一个函数模板,用于异步执行一个函数,并返回一个std::future对象,表示异步操作的结果。使用std::async可以方便地进行异步编程,避免了手动创建线程和管理线程的麻烦。下面是一个使用std::async的案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <future>
int calculate() {
// 模拟一个耗时的计算
std::this_thread::sleep_for(std::chrono::seconds(1));
return 42;
}
int main() {
std::future<int> future_result
= std::async(std::launch::async, calculate);
// 在这里可以做其他的事情
int result = future_result.get(); // 获取异步操作的结果
std::cout << result << std::endl; // 输出42
return 0;
}

这个例子中,我们使用std::async函数异步执行了一个耗时的计算,这个计算可以在另一个线程中执行,不会阻塞主线程。同时,我们也避免了手动创建线程和管理线程的麻烦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
#include<future>
using namespace std;

int func() {
int i = 0;
for (i = 0; i < 1000; i++)
{
i++;
}
return i;
}

int main()
{
std::future<int> future_result = std::async(std::launch::async, func);
cout << func() << endl;

cout << future_result.get() << endl;
return 0;
}

2. packaged_task

在C++中,packaged_task是一个类模板,用于将一个可调用对象(如函数、函数对象或Lambda表达式)封装成一个异步操作,并返回一个std::future对象,表示异步操作的结果。packaged_task可以方便地将一个函数或可调用对象转换成一个异步操作,供其他线程使用。

以下是packaged_task的基本用法:

\1. 定义可调用对象

1
2
3
int calculate(int x, int y) {
return x + y;
}

这里定义了一个函数calculate,用于将两个整数相加。 \2. 创建packaged_task对象

1
2
std::packaged_task<int(int, int)> task(calculate);
std::future<int> future_result = task.get_future();

这里创建了一个packaged_task对象,将函数calculate封装成异步操作,并返回一个std::future对象,表示异步操作的结果。

\3. 在其他线程中执行异步操作

1
2
std::thread t(std::move(task), 1, 2);
t.join();

这里创建了一个新的线程,并在这个线程中执行异步操作。由于packaged_task对象是可移动的,因此需要使用std::move()函数将task对象转移至新线程中执行。

\4. 获取异步操作的结果

1
2
int result = future_result.get();
std::cout << result << std::endl; // 输出3

在主线程中,我们可以使用future_result.get()方法获取异步操作的结果,并输出到控制台。 在这个例子中,我们成功地将一个函数calculate封装成了一个异步操作,并在其他线程中执行。通过packaged_task和future对象,我们可以方便地实现异步编程,使得代码更加简洁和易于维护。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<iostream>
#include<future>
using namespace std;

int func() {
int i = 0;
for (i = 0; i < 1000; i++)
{
i++;
}
return i;
}

int main()
{
std::packaged_task<int()> task(func);
auto future_result = task.get_future();

std::thread t1(std::move(task));
cout << func() << endl;

t1.join();
cout << future_result.get() << endl;

return 0;
}

3. promise

在C++中,promise是一个类模板,用于在一个线程中产生一个值,并在另一个线程中获取这个值。promise通常与future和async一起使用,用于实现异步编程。

以下是promise的基本用法: \1. 创建promise对象 std::promise p;

这里创建了一个promise对象,用于产生一个整数值。

\2. 获取future对象 std::future f = p.get_future();

通过promise对象的get_future()方法,可以获取与之关联的future对象,用于在另一个线程中获取promise对象产生的值。

\3. 在其他线程中设置值

1
2
3
4
std::thread t([&p]() {
p.set_value(42);
});
t.join();

这里创建了一个新的线程,并在这个线程中,使用promise对象的set_value()方法设置一个整数值42。

\4. 在主线程中获取值

1
2
int result = f.get();
std::cout << result << std::endl; // 输出42

在主线程中,我们可以使用future对象的get()方法获取promise对象产生的值,并输出到控制台。

在这个例子中,我们成功地使用promise和future对象实现了跨线程的值传递。通过promise和future对象,我们可以方便地实现异步编程,避免了手动创建线程和管理线程的麻烦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
#include<future>
using namespace std;

void func(std::promise<int>& f) {
f.set_value(1000);
}

int main()
{
std::promise<int> f;
auto future_result = f.get_future();

std::thread t1(func, std::ref(f));

t1.join();

cout << future_result.get() << endl;
return 0;
}

9.异步并发—— async future packaged_task promise
http://binbo-zappy.github.io/2024/11/27/cpp-多线程/9-异步并发—— async future packaged_task promise/
作者
Binbo
发布于
2024年11月27日
许可协议