C++ async 异步学习

作者:小侯不躺平.日期:2026/7/25

创建异步任务、延迟任务。任务或操作可以独立于主线程运行,主线程无需等待任务完成便可执行其他的任务,当异步的任务完成的时候可以通过某种机制获取其结果(std::future)

1、异步任务--async 正常使用环境 future.get

1#include<iostream>
2#include<thread>
3#include<chrono>
4#include<future>
5
6int task(int number) {
7    // 抛出异常 或 返回正常结果
8    std::cout<<"异步任务执行"<<std::endl;
9    // throw std::exception("异常抛出");
10    std::this_thread::sleep_for(std::chrono::seconds(2));
11    return 100+number;
12}
13
14void test()
15{
16    // 下面代码执行完成之后,异步任务就开始执行  async 参数1:任务类型(async异步任务 deferred延迟任务) 参数2:真正要执行的任务函数  参数3:传递给任务函数的参数
17    // 函数返回值 future类型 用于获取异步任务结果的对象 模版参数 < > 中填写任务函数的返回类型
18    std::future<int> fut = std::async(std::launch::async, task, 10);
19    std::cout<<"任务开始执行..."<<std::endl;
20
21    try
22    {
23        // 阻塞等待任务函数执行结束,并得到结果
24        int ret = fut.get();
25        std::cout<<"ret = "<< ret <<std::endl;
26    }
27    catch (const std::exception& ex)
28    {
29        std::cout<<ex.what()<<std::endl;
30    }
31    
32    std::cout<<"程序结束"<<std::endl;
33}
34
35int main()
36{
37    test();
38    return 0;
39}   

2、没有返回值的任务场景 future.wait wait_for wait_until

wait函数会阻塞等待任务函数执行结束(正常结束、异常结束),并不关心返回值。注意:如果任务函数抛出异常,wait函数不会再抛出异常,而是保存到std:future对象的内部,当调用get函数时会抛出异常。

A B 两个异步任务分别执行将不同的内容写入不同的文件中,然后由主线程将两个文件的内容合并到第三个文件中

1#include<iostream>
2#include<thread>
3#include<chrono>
4#include<future>
5#include<fstream>
6
7using namespace std;
8
9void write_file(string filename, string content)
10{
11    ofstream ofs(filename);
12    // 等待2s,表示耗时任务
13    this_thread::sleep_for(chrono::seconds(2));
14
15    ofs << content <<endl;
16    ofs.close();
17}
18
19void test()
20{
21    // 下面代码执行完成之后,线程函数就开始执行
22    future<void> fut1 = async(launch::async, write_file, "demo1.txt", "hello world");
23    future<void> fut2 = async(launch::async, write_file, "demo2.txt", "hello C++");
24    cout << "任务执行开始..." << endl;
25
26    // 等待异步任务执行完毕
27    fut1.wait();
28    fut2.wait();
29   
30    // 合并文件
31    ifstream ifs1("demo1.txt");
32    ifstream ifs2("demo2.txt");
33    ofstream ofs("demo.txt");
34
35    // 可以直接操作一个流的对象 参数2 就是结束的流
36    copy(istreambuf_iterator<char>(ifs1), istreambuf_iterator<char>(), ostreambuf_iterator<char>(ofs));
37    copy(istreambuf_iterator<char>(ifs2), istreambuf_iterator<char>(), ostreambuf_iterator<char>(ofs));
38
39    ifs1.close();
40    ifs2.close();
41    ofs.close();
42
43    cout<<"程序结束"<<endl;
44}
45
46int main()
47{
48    test();
49    return 0;
50}

3、非阻塞获取结果 wait_for wait_until 非阻塞的方式来获取异步的结果

wait_for 会在指定时间内等待任务状态的变化,如果任务没有结束,返回timeout,否则返回ready

wait_until则表示等到某个时间点,如果任务没有发生变化,则返回timeout,否则返回ready

1#include<iostream>
2#include<thread>
3#include<chrono>
4#include<future>
5#include<fstream>
6
7using namespace std;
8
9int calculate(int number)
10{
11    int result = 0;
12    for(int i = 0; i < number; ++i)
13    {
14        this_thread::sleep_for(chrono::seconds(1));
15        result += 10;
16    }
17    return result;
18}
19
20void test()
21{
22    future<int> fut = async(launch::async, calculate, 5);
23    cout << "任务开始执行..." << endl;
24
25    while(ture)
26    {
27        future_status status = fut.wait_for(chrono::seconds(1));
28        // future_status status = fur.wait_until(chrono::steady_clock().now + chrono::seconds(2));
29        if(status == future_status::ready)
30        {
31            cout<<"子线程结果"<< fut.get() <<endl;
32            break;
33        }
34        if(status == future_status::timeout)
35        {
36            cout<<"子任务尚未执行完成,做一会其他的事情..."<<endl;
37        }
38    }
39}
40
41int main()
42{
43    test();
44    return 0;
45}
46        

4、async的延时任务

将任务的执行推迟,知道确实需要时才开始执行。这种方式通常用于系统负载较高时,任务的结果又不立即需要的场景,帮助系统优化资源使用,提升整体性能。

1#include<iostream>
2#include<thread>
3#include<chrono>
4#include<future>
5#include<fstream>
6
7using namespace std;
8
9int task(int number)
10{
11    cout << "延迟任务执行" <<endl;
12    this_thread::sleep_for(std::chrono::seconds(8));
13    return 100+number;
14}
15
16void test01()
17{
18    // 任务不会马上执行
19    future<int> fut = async(launch::deferred, task,10);
20    
21    // 当调用 get、wait函数时,触发任务函数的执行
22    int ret = fut.get();
23    cout<<"ret = "<<ret <<endl;
24    // fut.wait();
25    
26    this_thread::sleep_for(std::chrono::seconds(3));
27}
28
29void test02()
30{
31    future<int> fut = async(launch::deferred, task, 10);
32    bool is_start = false;
33
34    while(true)
35    {
36        // 当延迟任务尚未执行前,wait_for 函数不会阻塞,会立即返回 有timeout deferred ready状态
37        future_status status = fut.wait_for(chrono::seconds(1));
38        // is_start 避免多开线程
39        if(status == future_status::deferred && !is_start)
40        {
41            cout<<"任务尚未开始执行..."<<endl;
42            // 新开一个线程去执行函数
43            thread([&fut]() {fut.wait();}).detach();
44            is_start = true;
45        }
46        
47        if(status == future_status::timeout)
48        {
49            cout<<"任务正在执行..."<<endl;
50        }
51
52        if(status == future_status::ready)
53        {
54            cout<<"任务执行完毕,执行结果是"<<fut.get()<<endl;
55            break;
56        }
57    }
58}
59
60int main()
61{
62    test02();
63    return 0;
64}

5、延时任务,独享和共享任务结果

future获取任务结果,它适合一次性获取结果。多次获取会导致一次。当任务需要在多个地方或者多次获取结果的时候,需要使用到shared_future代替future。

1#include<iostream>
2#include<thread>
3#include<chrono>
4#include<future>
5#include<fstream>
6
7using namespace std;
8
9// 可以在async的返回时直接写 shared_future    也可以用future的share获取一个shared_future
10
11void test()
12{
13    future<int> fut = async(launch::deferred, [](){
14        cout<<"延迟任务开始..."<<endl;
15        this_thread::sleep_for(chrono::seconds(2));
16        return 100;
17        });
18    // future 只能获取一次结果,重复获取会有异常
19    // shared_future 可以获取多次
20}

6、延时任务的案例

用户在查看某张照片,但是只有处理过的照片才能展示给用户看,我们可以

1、集中时间处理所有图片,这样会在一段时间大量占用系统的资源,会影响系统的性能

2、按需处理图片,用户请求那张就开那个线程处理,处理过的图像直接返回,剩余未处理的可以在系统空闲的时候进行处理

1#include<iostream>
2#include<thread>
3#include<chrono>
4#include<future>
5#include<fstream>
6#include<map>
7
8using namespace std;
9
10string data_analysis(string path)
11{
12    this_thread::sleep_for(chrono::seconds(10));
13    return path;
14}
15
16void test()
17{
18    map<string,tuple<bool,shared_future<string>>> tasks;
19
20    // 添加延迟图像处理的任务
21    tasks.insert({"a.png",{false,async(launch::deferred,data_analysis,"a.png")}});
22    tasks.insert({"b.png",{false,async(launch::deferred,data_analysis,"b.png")}});
23    tasks.insert({"c.png",{false,async(launch::deferred,data_analysis,"c.png")}});
24
25    // 用户查看图像
26    string name;
27    while(true)
28    {
29        cout<<"请输入查看的图像:";
30        cin>>name;
31        if(name == "exit")
32        {
33            for(auto &task : tasks)
34            {
35                cout<<task.first<<" "<<boolalpha<<get<0>(task.second)<<endl;
36            }
37            cout<<"--------------"<<endl;
38            break;
39        }
40
41        //查看图片的状态
42        auto& picture = tasks[name];
43        auto& is_ok = get<0>(picture);
44        auto& fut = get<1>(pitcture);
45        
46        if(is_ok)
47        {
48            cout<<"您要查看的图像是"<<fut.get()<<endl;
49            continue;
50        }
51
52        future_status status = fut.wait_for(chrono::seconds(1));
53        if(status == future_status::deferred)
54        {
55            cout<<"图像尚未处理,开始处理图像..."<<endl;
56            thread([&fut](){fut.wait();}).detach();
57        }
58
59        if(status == future_status::timeout)
60        {
61            cout<<"图像正在处理中"<<endl;
62        }
63        if(status == future_status::ready)
64        {
65            is_ok = true;
66            cout<<"您要查看的图像是1"<<fut.get()<<endl;
67        }
68        cout<<"============="<<endl';
69    }
70}
71
72int main()
73{
74    test();
75    return 0;
76}
77        

《C++ async 异步学习》 是转载文章,点击查看原文。


相关推荐


Spark 源码 | SparkSubmitArguments 参数解析(三)
董可伦2026/7/17

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站:https://www.captainai.net/dongkelun 前言 在第二篇文章 Spark 源码 | SparkSubmit 提交流程分析(二) 中,我们分析了 SparkSubmit 的提交流程,其中 doSubmit 方法会调用 parseArguments 解析命令行参数。本文详细介绍参数解析的过程。 版本 Spark 3.2.3 SparkSubmitArguments


LeetCode 459. 重复的子字符串
Best_Jerry2026/7/9

leetcode.cn/problems/re… programmercarl.com/0459.%E9%87… 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。   示例 1: 输入: s = "abab" 输出: true 解释: 可由子串 "ab" 重复两次构成。 示例 2: 输入: s = "aba" 输出: false 示例 3: 输入: s = "abcabcabcabc" 输出: true 解释: 可由子串 "abc" 重复四次构成。 (或子串 "abc


HDFS javaAPI-windows的IDEA中java文件在linux中的hadoop平台运行
chde2Wang2026/7/1

目录 运行前提 一、在IDEA的Maven项目中创建MkDirDemo类 (1)先确认目录结构(Maven 标准目录,必须按这个来) (2)hdfs java操作代码输入 (3)验证pom.xml文件中hadoop依赖是否和linux中hadoop版本一致 (4)确认 HDFS RPC 地址(关键) 二、Windows 本地配置 Hadoop 运行环境(必做,否则报 winutils 缺失) (1)下载 Windows 适配 hadoop 二进制包Hadoop3.x 下载对应


Obsidian - 使用 Share Note 分享笔记并自部署
LinXunFeng2026/6/22

欢迎关注微信公众号:FSA全栈行动 👋 一、前言 最近在整理 Obsidian 笔记时,经常会遇到一个小需求:想把某一篇笔记快速分享给别人,但又不想为了它单独搭建博客、导出 PDF 或复制到其它平台。 如果只是分享纯文本,复制粘贴当然可以。但 Obsidian 笔记里往往会有这些内容: 图片附件 代码块 Callout 提示块 标签、任务列表 Dataview 查询结果 当前主题样式和自定义 CSS 笔记之间的内部链接 这时候手动搬运就有点麻烦了,格式容易丢,图片也要重新处理。这里介绍一


RabbitMQ 从入门到精通:Spring Boot 实战三部曲(一)—— 基础核心与快速上手
绝知此事2026/6/14

RabbitMQ 从入门到精通:Spring Boot 实战三部曲(一)—— 基础核心与快速上手 专题导读:本系列共三篇,从基础到高级,带你系统掌握 RabbitMQ 在 Spring Boot 项目中的实战应用。 第一篇:基础核心与快速上手(本文)第二篇:进阶特性与可靠性保障第三篇:高级应用与性能优化 📖 前言 在当今的分布式系统中,消息队列已成为不可或缺的基础设施。RabbitMQ 作为最流行的消息中间件之一,以其可靠性、灵活性和易用性著称。 本文将从 RabbitMQ 的基础概念出


iOS、Android、Flutter 2026 流行框架对比
王若风2026/6/7

参考文章:iOS、Android、Flutter 流行框架对比(原始链接) 我把我 2 年前的一篇博客文章进行了一次“重写”,于是有了这篇。 原文的选题很实用,结构也很清晰:按布局、网络请求、图片加载三个维度,把 iOS、Android、Flutter 常见框架放在一起横向看。 帮助移动端开发洞察各端核心框架的流行趋势,提供洞察和选项参考。 但原文的数据,放到 2026 年 6 月再看,已经有点过期了。 比如 Jetpack Compose 已经不是“新趋势”,而是 Android 新项目的


数据采集卡技术全解:从硬件架构到行业应用
zlinear数据采集卡2026/5/31

目录 数据采集卡技术全解:从硬件架构到行业应用 一、数据采集卡基础概念与分类体系 1.1 核心概念:连接物理世界与数字世界的桥梁 1.2 数据采集卡的核心功能构成 1.3 与传统测量仪器的本质区别 1.4 多维度的分类体系 1.4.1 按核心性能(采样率)分类 1.4.2 按总线接口类型分类 1.4.3 按功能与应用分类 章节小结 二、硬件架构深度解析 2.1 整体架构视图:从信号入口到数据出口 2.2 模拟前端:信号的“守门人”与“化妆师” 2.3 数据转换核心:A


技术选型决策树:什么团队、什么项目该选什么框架 | 跨平台框架深度对决(4)
陆业聪2026/5/10

跨平台框架深度对决系列 · 第4/4篇(完结篇) Flutter vs KMP vs KuiKly vs RN,谁是2026年的最优解 第1篇:跨平台框架全景图——Flutter/KMP/KuiKly/RN的2026年格局 第2篇:渲染引擎与性能拆解——自绘vs原生渲染vs Bridge的终极对决 第3篇:架构哲学与工程化——从开发体验到CI/CD的全维度对比 第4篇:技术选型决策树——什么团队、什么项目该选什么框架(本篇 · 完结) 上个月,有三个不同的朋友分别找我聊跨平台选型。 第一个是创业


RAG 系列(二):用 LangChain 搭建你的第一个 RAG Pipeline
冬奇Lab2026/4/30

从 100 行代码到生产级 Pipeline 上一篇我们用手写 Python 搭了一个最小 RAG,100 行代码跑通了核心逻辑。但如果你想把那套代码搬到生产环境,很快就会撞上一堵墙。 要加载 PDF? 你需要 PyPDF2 或 pdfplumber,然后发现表格、页眉页脚的解析是一场噩梦。 要切分文本? 你那个朴素的 text.split("\n\n") 会把句子拦腰截断、破坏代码块,或者切出超长的块直接把 Token 上限撑爆。 想换个向量数据库? 祝你下午愉快——每个数据库的 API 都不


告别 jq 噩梦!这款 JSON 神器 fx 让你在终端体验“丝滑”的数据操作
GetcharZp2026/4/21

还在为复杂的 jq 语法抓狂?antonmedv/fx 带着交互式 TUI 和纯正 JavaScript 语法来了!JSON 调试、过滤、转换,一个工具全搞定。 在程序员的日常摸鱼……哦不,日常开发中,JSON 绝对是出现频率最高的朋友。 不管是调用后端接口、查看 K8s 配置,还是分析爬虫数据,面对满屏密密麻麻、甚至没有缩进的原始 JSON 字符串,我们的第一反应通常是: 打开浏览器,搜索“JSON 在线格式化”。 把数据粘进去,点一下“美化”。 忍受网页弹窗广告,或者担心敏感数据泄露。

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读