news 2026/2/28 17:06:15

C++11 异步编程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++11 异步编程

std::async+std::future:最简单的异步任务

1. 作用

  • std::async启动异步任务(可选择 “开新线程” 或 “延迟执行”),并返回std::future接收结果;
  • std::future独占式结果容器—— 存储异步任务的结果,结果只能被获取一次。

2.std::async核心函数

// 形式1:指定启动策略 template <class Fn, class... Args> std::future<typename std::result_of<Fn(Args...)>::type> async(std::launch policy, Fn&& fn, Args&&... args); // 形式2:默认策略(编译器自动选择) template <class Fn, class... Args> std::future<typename std::result_of<Fn(Args...)>::type> async(Fn&& fn, Args&&... args);
  • 参数说明:
    • policy:启动策略(控制任务执行方式):
      • std::launch::async:强制立刻开新线程执行任务;
      • std::launch::deferred:延迟执行(直到调用future::get()时,在当前线程执行);
    • fn:异步任务(函数、lambda、函数对象等);
    • Args...:任务fn的参数;
  • 返回值:std::future<T>Tfn的返回类型),用于接收任务结果。

3.std::future核心成员函数

std::future独占式结果容器(一个future只能对应一个异步结果),因此它的拷贝构造函数和拷贝赋值运算符被显式删除,只能通过移动语义转移所有权(用std::move)。

函数作用
T get()阻塞当前线程,等待任务完成并返回结果;⚠️ 注意:只能调用一次,调用后future失效。
void wait()阻塞线程直到任务完成,但不获取结果
future_status wait_for(const chrono::duration<Rep, Period>& rel_time)等待指定时长,返回任务状态:-ready:任务完成;-timeout:超时未完成;-deferred:任务延迟执行。

4. 样例:用async+future后台计算

#include <iostream> #include <future> #include <chrono> using namespace std; // 异步任务:计算a+b int add(int a, int b) { this_thread::sleep_for(chrono::seconds(2)); // 模拟耗时 return a + b; } int main() { // 1. 启动异步任务(显式指定async策略,开新线程) future<int> fut = async(launch::async, add, 3, 5); // 2. 主线程做其他事 cout << "主线程:等待后台计算..." << endl; // 3. 等待任务状态(最多等1秒) future_status status = fut.wait_for(chrono::seconds(1)); if (status == future_status::timeout) { cout << "主线程:等待超时,任务还在运行..." << endl; } // 4. 获取结果(阻塞直到任务完成) int result = fut.get(); cout << "主线程:计算结果是 " << result << endl; // 输出8 return 0; }

二、std::promise:主动向线程外传递结果

1. 作用

std::promise主动承诺结果的工具:一个线程通过promise主动设置结果,另一个线程通过绑定的future获取结果(适合 “线程内主动传结果” 的场景)。

2.std::promise核心成员函数

函数作用
future<T> get_future()获取与当前promise绑定的future;⚠️ 注意:一个promise只能调用一次。
void set_value(const T& val)设置任务结果(“兑现承诺”);⚠️ 注意:只能调用一次,否则崩溃。
void set_exception(exception_ptr e)设置异常结果 —— 其他线程调用future::get()时会抛出该异常。

3. 样例:用promise主动传结果

#include <iostream> #include <future> #include <thread> #include <chrono> using namespace std; // 线程函数:用promise设置结果 void calc(promise<int>& prom) { this_thread::sleep_for(chrono::seconds(2)); // 模拟计算 int res = 10 * 5; prom.set_value(res); // 主动设置结果 } int main() { // 1. 创建promise promise<int> prom; // 2. 获取绑定的future future<int> fut = prom.get_future(); // 3. 启动线程,传递promise(必须用ref传引用) thread t(calc, ref(prom)); // 4. 主线程获取结果 cout << "主线程:等待线程传结果..." << endl; int result = fut.get(); cout << "主线程:线程计算结果是 " << result << endl; // 输出50 t.join(); return 0; }

三、std::packaged_task:包装任务的容器

1. 作用

std::packaged_task任务包装器:将 “函数、lambda” 等可调用对象包装成 “异步任务”,同时绑定future—— 执行包装的任务后,结果会存入future(适合 “封装任务到线程池 / 队列” 的场景)。

2.std::packaged_task核心成员函数

函数作用
explicit packaged_task(Fn&& fn)构造函数:用可调用对象fn初始化任务。
future<T> get_future()获取与包装任务绑定的future;⚠️ 注意:一个packaged_task只能调用一次。
void operator()(Args&&... args)执行包装的任务,args是任务参数;执行后结果存入对应的future

3. 样例:用packaged_task包装阶乘任务

#include <iostream> #include <future> #include <thread> using namespace std; // 要包装的任务:计算n的阶乘 int factorial(int n) { int res = 1; for (int i = 1; i <= n; ++i) res *= i; return res; } int main() { // 1. 包装任务(把factorial包装成packaged_task) packaged_task<int(int)> task(factorial); // 2. 获取绑定的future future<int> fut = task.get_future(); // 3. 启动线程执行任务(必须用move转移任务所有权) thread t(move(task), 5); // 计算5的阶乘 // 4. 获取结果 cout << "等待阶乘计算..." << endl; int result = fut.get(); cout << "5的阶乘是 " << result << endl; // 输出120 t.join(); return 0; }

四、std::shared_future:共享结果的容器

1. 作用

std::shared_futurestd::future共享版:可被拷贝,多个线程能通过不同的shared_future获取同一个结果(future是独占的,shared_future是共享的)。

std::shared_future的构造函数

1. 默认构造函数

shared_future() noexcept;

作用:创建一个 “空的”shared_future,不关联任何异步结果(valid()返回false)。

2. 移动构造函数(从std::future

shared_future(future<T>&& other) noexcept;

作用:用一个std::future移动构造shared_futurefuture会失效(转移了结果的所有权)。

这是最常用的构造方式之一(future::share()本质就是返回这种方式构造的shared_future)。

3. 拷贝构造函数

原型

shared_future(const shared_future& other) noexcept;

作用:拷贝另一个shared_future,两个shared_future关联同一个异步结果(这是shared_future实现 “共享结果” 的核心)。

4. 移动构造函数(从std::shared_future

原型

shared_future(shared_future&& other) noexcept;

作用:用另一个shared_future移动构造,shared_future会变成空的(转移了结果的所有权)。

2.std::shared_future核心成员函数

函数作用
const T& get() const阻塞线程(若任务未完成),返回结果;✅ 特点:可多次调用,不会失效。
void wait()阻塞线程直到任务完成,不获取结果。

3. 样例:多线程共享shared_future结果

#include <iostream> #include <future> #include <thread> #include <vector> using namespace std; // 异步任务:生成随机数 int generate_rand() { srand(time(0)); return rand() % 100; } // 线程函数:共享结果 void print_result(shared_future<int> fut, int thread_id) { int res = fut.get(); // 可多次调用 cout << "线程" << thread_id << "获取到的随机数:" << res << endl; } int main() { // 1. 启动异步任务,获取future future<int> fut = async(launch::async, generate_rand); // 2. 转换为shared_future(共享结果) shared_future<int> shared_fut = fut.share(); // 3. 启动3个线程共享结果 vector<thread> threads; for (int i = 0; i < 3; ++i) { threads.emplace_back(print_result, shared_fut, i); } // 等待线程完成 for (auto& t : threads) t.join(); return 0; }

运行结果(3 个线程拿到同一个随机数):

线程0获取到的随机数:42 线程1获取到的随机数:42 线程2获取到的随机数:42
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/28 13:37:38

MinerU金融研报解析:投资观点自动摘要系统

MinerU金融研报解析&#xff1a;投资观点自动摘要系统 1. 引言 1.1 金融信息处理的效率瓶颈 在金融投研领域&#xff0c;分析师每天需要处理大量非结构化文档&#xff0c;包括上市公司年报、行业研究报告、券商策略点评等。传统方式依赖人工阅读与摘录&#xff0c;耗时长、成…

作者头像 李华
网站建设 2026/2/24 22:16:57

Qwen-Image-2512-ComfyUI部署案例:校园创意设计辅助系统搭建

Qwen-Image-2512-ComfyUI部署案例&#xff1a;校园创意设计辅助系统搭建 1. 引言 随着人工智能在创意设计领域的深入应用&#xff0c;高校师生对高效、易用的AI图像生成工具需求日益增长。传统的设计辅助手段依赖大量人工构思与素材积累&#xff0c;效率较低且创意边界受限。…

作者头像 李华
网站建设 2026/2/24 12:32:51

Qwen3-1.7B调用踩坑记录:这些错误千万别犯

Qwen3-1.7B调用踩坑记录&#xff1a;这些错误千万别犯 1. 引言 随着大模型技术的快速发展&#xff0c;Qwen3系列作为通义千问团队于2025年推出的最新一代开源语言模型&#xff0c;凭借其高效的性能和灵活的部署能力&#xff0c;迅速成为开发者关注的焦点。其中&#xff0c;Qw…

作者头像 李华
网站建设 2026/2/28 13:28:41

5个通义千问3-4B-Instruct镜像推荐:免配置一键部署入门必看

5个通义千问3-4B-Instruct镜像推荐&#xff1a;免配置一键部署入门必看 近年来&#xff0c;随着大模型轻量化趋势的加速&#xff0c;端侧部署的小参数大语言模型正成为开发者和AI爱好者的新宠。其中&#xff0c;通义千问3-4B-Instruct-2507&#xff08;Qwen3-4B-Instruct-2507…

作者头像 李华
网站建设 2026/2/28 14:07:49

BGE-Reranker-v2-m3性能优化指南:精排速度提升3倍

BGE-Reranker-v2-m3性能优化指南&#xff1a;精排速度提升3倍 1. 引言 在当前的检索增强生成&#xff08;RAG&#xff09;系统中&#xff0c;向量检索虽能快速召回候选文档&#xff0c;但其基于距离匹配的机制容易受到“关键词陷阱”干扰&#xff0c;导致相关性排序不准。为此…

作者头像 李华
网站建设 2026/2/24 22:51:51

通义千问2.5-7B-Instruct语音助手:文本转语音集成方案

通义千问2.5-7B-Instruct语音助手&#xff1a;文本转语音集成方案 1. 引言 随着大语言模型在自然语言理解与生成能力上的持续突破&#xff0c;将高质量的文本输出转化为自然流畅的语音交互已成为智能助手、客服系统、教育工具等场景的核心需求。通义千问2.5-7B-Instruct作为阿…

作者头像 李华