一个std::async的示例

news/2025/2/26 13:45:36

目录

一、问题引出

二、关键点解释

1.生成随机数

2.异步启动两个操作

3.检查异步任务是否为延迟执行并轮询任务状态

4.等待所有任务完成并处理异常

三、总结


一、问题引出

从《c++标准库》(第2版)看到一个std::async的例子。演示了使用 std::async 和std::future的异步任务执行。

#include <future>
#include <thread>
#include <chrono>
#include <random>
#include <iostream>
#include <exception>
using namespace std;

void doSomething (char c)
{
    // random-number generator (use c as seed to get different sequences)
    default_random_engine dre(c);
    uniform_int_distribution<int> id(10,1000);
 
    // loop to print character after a random period of time
    for (int i=0; i<10; ++i) {
        this_thread::sleep_for(chrono::milliseconds(id(dre)));
        cout.put(c).flush();
    }
}

int main()
{
    cout << "starting 2 operations asynchronously" << endl;

    // start two loops in the background printing characters . or +
    auto f1 = async([]{ doSomething('.'); });
    auto f2 = async([]{ doSomething('+'); });

    // if at least one of the background tasks is running
    if (f1.wait_for(chrono::seconds(0)) != future_status::deferred ||
        f2.wait_for(chrono::seconds(0)) != future_status::deferred) {
        // poll until at least one of the loops finished
        while (f1.wait_for(chrono::seconds(0)) != future_status::ready &&
               f2.wait_for(chrono::seconds(0)) != future_status::ready) {
            //...;
            this_thread::yield();  // hint to reschedule to the next thread
        }
    }
    cout.put('\n').flush();

    // wait for all loops to be finished and process any exception
    try {
        f1.get();
        f2.get();
    }
    catch (const exception& e) {
        cout << "\nEXCEPTION: " << e.what() << endl;
    }
    cout << "\ndone" << endl;
}

二、关键点解释

1.生成随机数

  • default_random_engine dre(c);:创建一个默认的随机数生成器 dre,并使用字符 c 作为种子。这样不同的调用会得到不同的随机数序列。

  • uniform_int_distribution<int> id(10,1000);:创建一个均匀整数分布对象 id,用于生成范围在 10 到 1000 之间的随机整数。

2.异步启动两个操作

auto f1 = async([]{ doSomething('.'); });
auto f2 = async([]{ doSomething('+'); });
  • std::async 是一个用于异步执行任务的函数模板。它会启动一个新的线程(或者使用线程池中的线程)来执行传入的可调用对象(这里是 lambda 表达式)。

  • f1 和 f2 是 std::future 对象,用于获取异步操作的结果。这里的异步操作是调用 doSomething 函数,分别传入字符 . 和 +

3.检查异步任务是否为延迟执行并轮询任务状态

if (f1.wait_for(chrono::seconds(0)) != future_status::deferred ||
    f2.wait_for(chrono::seconds(0)) != future_status::deferred) {
    while (f1.wait_for(chrono::seconds(0)) != future_status::ready &&
           f2.wait_for(chrono::seconds(0)) != future_status::ready) {
        this_thread::yield();  // hint to reschedule to the next thread
    }
}
cout.put('\n').flush();
  • f1.wait_for(chrono::seconds(0)) 和 f2.wait_for(chrono::seconds(0)):检查 f1 和 f2 对应的异步任务的状态,chrono::seconds(0) 表示不等待,立即返回任务状态。

  • future_status::deferred 表示任务是延迟执行的。如果至少有一个任务不是延迟执行的,则进入内层循环。

  • 内层 while 循环会不断检查 f1 和 f2 的状态,直到至少有一个任务完成(状态为 future_status::ready)。

  • this_thread::yield();:提示操作系统将当前线程的执行权让给其他线程,避免忙等待。

4.等待所有任务完成并处理异常

try {
    f1.get();
    f2.get();
}
catch (const exception& e) {
    cout << "\nEXCEPTION: " << e.what() << endl;
}
  • f1.get() 和 f2.get():阻塞当前线程,直到 f1 和 f2 对应的异步任务完成,并获取任务的结果。如果任务抛出异常,get() 函数会重新抛出该异常。

  • catch (const exception& e):捕获可能抛出的异常,并输出异常信息。

三、总结

这段代码的主要功能是异步启动两个任务,每个任务会随机暂停一段时间后输出一个字符,程序会等待至少一个任务完成,最后等待所有任务完成并处理可能的异常。


http://www.niftyadmin.cn/n/5868787.html

相关文章

《零基础学会!如何用 sql+Python 绘制柱状图和折线图,数据可视化一看就懂》

在数据驱动的时代&#xff0c;MySQL 是最常用的关系型数据库管理系统之一&#xff0c;广泛应用于各类数据存储和处理场景。数据分析的过程不仅仅是收集数据&#xff0c;还包括数据的清洗、转换、查询以及最终的报告和可视化。在本文中&#xff0c;我们将通过实际案例来介绍如何…

Java+SpringBoot+Vue+数据可视化的音乐推荐与可视化平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在互联网技术以日新月异之势迅猛发展的浪潮下&#xff0c;5G 通信技术的普及、云计算能力…

Golang适配达梦数据库连接指定模式

1、达梦官方适配文档&#xff1a;https://eco.dameng.com/document/dm/zh-cn/start/GO_DM_NEW.html 2、连接指定模式方式&#xff1a;dataSourceName : “dm://SYSDBA:*****192.168.40.1:5237?schemaTESTDB” 3、beego orm适配遇到问题&#xff1a; 3.1、q:同一用户下不同模式…

Go Channel 高级模式实战:超时控制与广播机制的深度解析

1. 前言 在 Go 语言的并发世界中&#xff0c;channel 是我们手中的一把利器&#xff0c;它让 goroutine 间的通信变得优雅而高效。如果你已经用 channel 实现过简单的生产者-消费者模型&#xff0c;或者在 select 中处理过并发任务&#xff0c;那么恭喜你&#xff0c;你已经迈…

如何实现将http请求转化为rpc请求

以下是10个可以实现HTTP请求转发到内部RPC服务的GitHub项目推荐&#xff0c;这些项目涵盖了多种语言和框架&#xff0c;适用于不同的技术栈和需求&#xff1a; 1. **grpc-gateway** grpc-gateway 是一个流行的开源项目&#xff0c;用于将HTTP请求转发到gRPC服务。它支持通…

第9章 机器学习与统计模型

这一章重点探讨统计模型和机器学习模型&#xff0c;两个大的主题都建立在数据的基础之上&#xff0c;所以要熟练掌握对数据的处理与分析。实际上&#xff0c;机器学习本身就是统计模型的延伸&#xff0c;是在大数据背景下传统统计方法捉襟见肘了&#xff0c;所以才考虑引入机器…

电脑连接示波器显示波形

通过网线连接示波器和电脑&#xff0c;将示波器波形显示在电脑上直接复制图片至报告中&#xff0c;以下是配置步骤。 一、设备 网线&#xff0c;Tektronix示波器&#xff0c;电脑 二、使用步骤 1.用网线连接电脑和示波器 2.电脑关掉WiFi&#xff0c;查看IPv4网关地址&#xf…

2014年下半年试题一:论软件需求管理

论文库链接&#xff1a;系统架构设计师论文 论文题目 软件需求管理是一个对系统需求变更了解和控制的过程。需求管理过程与需求开发过程相互关联&#xff0c;初始需求导出的同时就要形成需求管理规划&#xff0c;一旦启动了软件开发过程需求管理活动就紧密相伴。 需求管理过程中…