std::future & promise
future/promise是 C++ 异步编程的基础,提供线程间传递值和异常的标准机制。
future 与 promise
cpp
#include <future>
#include <thread>
// promise:写端(生产者)
// future:读端(消费者)
std::promise<int> prom;
std::future<int> fut = prom.get_future();
// 在另一个线程中设置值
std::thread t([&prom] {
std::this_thread::sleep_for(std::chrono::seconds(1));
prom.set_value(42); // 设置结果
});
// 主线程等待结果
int result = fut.get(); // 阻塞直到有值
std::cout << result << "\n"; // 42
t.join();
// 传递异常
std::promise<int> prom2;
std::future<int> fut2 = prom2.get_future();
std::thread t2([&prom2] {
try {
throw std::runtime_error("计算失败");
} catch (...) {
prom2.set_exception(std::current_exception());
}
});
try {
int val = fut2.get(); // 重新抛出异常
} catch (const std::exception& e) {
std::cout << "异常: " << e.what() << "\n";
}
t2.join();std::async
cpp
#include <future>
// async:最简单的异步执行方式
auto fut = std::async(std::launch::async, []() -> int {
std::this_thread::sleep_for(std::chrono::seconds(1));
return 42;
});
// 做其他工作...
std::cout << "等待结果...\n";
int result = fut.get(); // 等待并获取结果
std::cout << "结果: " << result << "\n";
// 启动策略
std::launch::async // 立即在新线程执行
std::launch::deferred // 延迟执行(调用 get() 时在当前线程执行)
std::launch::async | std::launch::deferred // 由实现决定(默认)
// 并行计算示例
auto f1 = std::async(std::launch::async, compute_part1);
auto f2 = std::async(std::launch::async, compute_part2);
auto f3 = std::async(std::launch::async, compute_part3);
auto r1 = f1.get();
auto r2 = f2.get();
auto r3 = f3.get();
auto total = combine(r1, r2, r3);packaged_task
cpp
#include <future>
// packaged_task:将函数包装为可异步执行的任务
std::packaged_task<int(int, int)> task([](int a, int b) {
return a + b;
});
std::future<int> fut = task.get_future();
// 在另一个线程执行
std::thread t(std::move(task), 3, 4);
t.join();
std::cout << fut.get() << "\n"; // 7
// 用于线程池
class SimplePool {
std::vector<std::thread> workers_;
std::queue<std::packaged_task<void()>> tasks_;
std::mutex mtx_;
std::condition_variable cv_;
bool stop_ = false;
public:
template<typename F>
auto submit(F&& f) {
using R = std::invoke_result_t<F>;
std::packaged_task<R()> task(std::forward<F>(f));
auto fut = task.get_future();
{
std::lock_guard lock(mtx_);
tasks_.emplace([t = std::move(task)]() mutable { t(); });
}
cv_.notify_one();
return fut;
}
};shared_future
cpp
// future 只能 get() 一次,shared_future 可以多次
std::promise<std::string> prom;
std::shared_future<std::string> shared = prom.get_future().share();
// 多个线程等待同一个结果
std::vector<std::thread> threads;
for (int i = 0; i < 5; ++i) {
threads.emplace_back([shared, i] {
auto result = shared.get(); // 所有线程都能获取
std::cout << "线程 " << i << " 收到: " << result << "\n";
});
}
prom.set_value("广播消息");
for (auto& t : threads) t.join();超时等待
cpp
std::future<int> fut = std::async(std::launch::async, []() {
std::this_thread::sleep_for(std::chrono::seconds(5));
return 42;
});
// 等待一段时间
auto status = fut.wait_for(std::chrono::seconds(1));
switch (status) {
case std::future_status::ready:
std::cout << "结果: " << fut.get() << "\n";
break;
case std::future_status::timeout:
std::cout << "超时,继续等待...\n";
break;
case std::future_status::deferred:
std::cout << "延迟执行\n";
break;
}
// 等待到特定时间点
auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
if (fut.wait_until(deadline) == std::future_status::ready) {
std::cout << fut.get() << "\n";
}关键认知
std::async 是最简单的异步方式,但注意:返回的 future 析构时会阻塞等待(不要忽略返回值!)。packaged_task 适合线程池场景。shared_future 用于广播结果给多个等待者。