C++中的异步编程:std::future与std::promise的结合
欢迎来到今天的讲座!今天我们要聊一聊C++中一个非常有趣的话题——异步编程。如果你曾经在写程序时遇到过“等待”这个问题,那么你一定会对今天的主题感兴趣。想象一下,你的程序就像一个餐馆的服务员,如果他一直在厨房门口等着厨师做完菜再服务下一位客人,那效率肯定低得可怜。而我们今天要讲的std::future
和std::promise
,就是帮助我们的服务员更高效地工作的好帮手!
异步编程是什么?
在传统的同步编程中,程序按照代码的顺序一步一步执行,每一步都必须等到前一步完成才能继续。而在异步编程中,程序可以同时处理多个任务,不需要一直等待某个任务完成。这就像是让服务员可以先去招呼其他客人,等厨师做好菜后再回来取餐。
std::future 和 std::promise 是什么?
- std::future 是一个容器,用来存储未来的结果。你可以把它想象成一个快递包裹,你现在下单了,但货物还在路上。
- std::promise 是一个生产者,用来设置这个未来的结果。它就像是快递公司,负责把货物送到你下单的地方。
两者的关系可以用一句话概括:std::promise
设置结果,std::future
获取结果。
让我们来看一个简单的例子
假设我们需要计算两个数的和,但是这个计算可能需要一些时间,所以我们想让它在后台进行,而不阻塞主线程。
#include <iostream>
#include <future>
#include <thread>
int main() {
// 创建一个 promise 对象
std::promise<int> sumPromise;
// 获取 future 对象
std::future<int> sumFuture = sumPromise.get_future();
// 启动一个线程来计算两个数的和
std::thread t([&sumPromise]() {
int a = 10, b = 20;
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
sumPromise.set_value(a + b); // 设置结果
});
std::cout << "Waiting for the result..." << std::endl;
// 等待结果并获取
int result = sumFuture.get(); // 阻塞直到结果可用
std::cout << "The result is: " << result << std::endl;
t.join(); // 等待线程结束
return 0;
}
在这个例子中,我们创建了一个std::promise
对象,并通过它获得了std::future
对象。然后我们在一个独立的线程中计算两个数的和,并使用set_value
方法将结果传递给std::future
。主线程会一直等待,直到std::future
有结果为止。
std::future 和 std::promise 的状态
状态 | 描述 |
---|---|
ready | 结果已经准备好,可以通过 get() 方法获取 |
not ready | 结果还没有准备好,调用 get() 会阻塞,直到结果准备好 |
invalid | std::future 对象已经被移动或销毁,无法再获取结果 |
std::future 的常见用法
除了上面提到的get()
方法,std::future
还有一些其他有用的方法:
- wait(): 主动等待结果,不会返回任何值。
- wait_for(): 等待一段时间后返回,如果在这段时间内结果没有准备好,则返回
std::future_status::timeout
。 - wait_until(): 等待到指定的时间点,如果到那时结果还没有准备好,则返回
std::future_status::timeout
。
std::promise 的常见用法
- set_value(): 设置结果的值。
- set_exception(): 设置异常,用于处理可能出现的错误。
实战演练:多线程数据处理
让我们再来看一个稍微复杂一点的例子,假设我们需要从多个线程中收集数据,并将它们汇总在一起。
#include <iostream>
#include <vector>
#include <future>
#include <thread>
// 模拟耗时的数据处理函数
int processData(int data) {
std::this_thread::sleep_for(std::chrono::seconds(1));
return data * 2;
}
int main() {
std::vector<std::future<int>> futures;
std::vector<std::promise<int>> promises;
// 创建多个 promise 和 future 对象
for (int i = 0; i < 5; ++i) {
std::promise<int> promise;
promises.push_back(std::move(promise));
futures.push_back(promises.back().get_future());
}
// 启动多个线程来处理数据
for (size_t i = 0; i < promises.size(); ++i) {
std::thread t([i, &promises]() {
int result = processData(i);
promises[i].set_value(result); // 设置结果
});
t.detach(); // 分离线程
}
// 收集所有结果
int total = 0;
for (auto& fut : futures) {
total += fut.get(); // 获取每个线程的结果
}
std::cout << "Total result: " << total << std::endl;
return 0;
}
在这个例子中,我们创建了多个std::promise
和std::future
对象,并启动了多个线程来处理数据。每个线程处理完数据后,都会通过std::promise
将结果传递给对应的std::future
。最后,我们在主线程中收集所有结果并计算总和。
总结
今天我们一起探讨了C++中std::future
和std::promise
的结合使用。通过这两个工具,我们可以轻松实现异步编程,提高程序的效率。记住,std::promise
是用来设置结果的,而std::future
是用来获取结果的。希望今天的讲座对你有所帮助,下次再见!