rust学习十七.1、async和await

news/2025/1/16 16:35:29/文章来源:https://www.cnblogs.com/lzfhope/p/18671345

本文对应相关书籍17.1章节。

先言:async和多线程没有什么密切关系,当然也不是毫无关系!

一、async在rust到底是什么

async中文的意思是异步,在编程中指的是:执行一段代码,主线程可以在等待完成之前,先做其它事情。

如果有写过前端代码,就明白这个东西。例如经典的jquery的ajax默认就是异步执行的。

 

原书花费了一段文字先解释:并行和并发

 * 1.并行(parallel)和并发(concurrency)都有一段时间内共同执行多个任务的意思
 * 2.并行指的是在同一时刻,有多个任务在执行。并发是指在某一时间段内,有多个任务在交替执行
 * 3.并发某种程度上理解为资源不够,分时处理;并行理解为资源充足,同时处理。
 * 4.当使用 Rust 中的 async 时,我们总是在处理并发
 * 5.取决于硬件、操作系统和所使用的异步运行时(async runtime)-- 稍后会介绍更多的异步运行时!
 *   并发也可能在底层使用了并行 --  这个需要特别注意

说了这么一大段就是为了说明一个事情:使用 Rust 中的 async 时,我们总是在处理并发

也就是说,一般情况下,在rust中使用异步,基本就是意味着是cpu分时处理,但具体怎么实现和代码以及系统系统有关!!!

 

二、async、await和future

await-等待

future-未来,rust中用于表示一个数据类型:现在不会有,但是过了一段时间会有

这些都是很熟悉的字眼,在java,js中是常常出现的。

 * 1.future 是一个现在可能还没有准备好但将在未来某个时刻准备好的值
 * 2.Rust 提供了 Future trait 作为基础组件,这样不同的异步操作就可以在不同的数据结构上实现
 * 3.每一个实现了 Future 的类型会维护自己的进度状态信息和 “ready” 的定义
 * 4.async 关键字可以用于代码块和函数
 * 5.在一个 async 块或 async 函数中,可以使用 await 关键字来等待一个 future 准备就绪,这一过程称为 等待一个 future
 * 6.检查一个 future 并查看其值是否已经准备就绪的过程被称为 轮询(polling)
 * 7.在大多数情况下,编写异步 Rust 代码时,我们使用 async 和 await 关键字。
 *    Rust 将其编译为等同于使用 Future trait 的代码,这非常类似于将 for 循环编译为等同于使用 Iterator trait 的代

 

三、示例

use trpl::{Either, Html};
use std::thread;fn main() {let args: Vec<String> = std::env::args().collect();println!("{:?}", args);//注意async关键字,并不会导致开启一个新的线程,仅仅意味着可以在内部使用await关键字等待异步操作完成。trpl::run(async {//lazy future 这里不会执行let title_fut_1 = page_title(&args[1]);//lazy future 这里不会执行let title_fut_2 = page_title(&args[2]);//race中的代码使用future::select执行并发,并返回最先完成的future。//因为这里真正开始执行,所以才会在多次运行的时候,返回可能不同的结果//race方法返回的是一个Either类型,Either是一个枚举类型,有两个值,Left和Right。let (url, maybe_title) = match trpl::race(title_fut_1, title_fut_2).await {Either::Left(left) => left,Either::Right(right) => right,};println!("{url} returned first");match maybe_title {Some(title) => println!("Its page title is: '{title}'"),None => println!("Its title could not be parsed."),}})
}
/*** 带了async的函数会返回一个future,这个future的类型是impl Future<Output = ()>,* output是一个泛型参数,这里是(),表示这个future的返回值是一个元组,*/
async fn page_title(url: &str) -> (&str, Option<String>) {//这个语句会证实函数page_title是运行在主线程中...,并不是多线程的.println!("{}",url);println!("线程{:?}正在执行", thread::current().id());let text = trpl::get(url).await.text().await;let title = Html::parse(&text).select_first("title").map(|title| title.inner_html());(url, title)
}

 

注意:第一次执行,你会怀疑是不是卡死了,这个不是问题,是rusts-script需要耗费时间处理trpl(后者又依赖很多乱起八糟的),所以耗时颇长.

rust-script -d trpl 17.2_future.rs  https://www.cnblogs.com/lzfhope/p/18459068  https://www.cnblogs.com/lzfhope/p/18664452

这个命令执行了几次:

可以看到,结果会有所不同,这意味着 两个page_title在执行的时候不是固定,不是串行的!

 

这个trpl是rust提供的示例代码,下面是感兴趣的部分:

pub fn run<F: Future>(future: F) -> F::Output {let rt = Runtime::new().unwrap();rt.block_on(future)
}pub async fn race<A, B, F1, F2>(f1: F1, f2: F2) -> Either<A, B>
whereF1: Future<Output = A>,F2: Future<Output = B>,
{let f1 = pin!(f1);let f2 = pin!(f2);match future::select(f1, f2).await {Either::Left((a, _f2)) => Either::Left(a),Either::Right((b, _f1)) => Either::Right(b),}
}

 

这个Runtime是tokio单元包的成员,表示运行时(需要注意的是,rust反复强调运行时可以自建)

future::select 这个函数用于并发执行多个future,并返回一个future值。

四、简单执行async+await是什么样的?

前面的例子,有启用并发。 这也是常规的做法。

但是我也感兴趣,如果不用并发又是什么样的?

先说结论:就是什么也没有发生

use std::thread;struct Hero {name: String,age: u32,
}fn main() {let hero = Hero {name: "孙悟空".to_string(),age: 100,};let ws = Hero {name: "武松".to_string(),age: 99,};let str1 = run(&hero);let str2 = run(&ws);
}async fn fight(h: &Hero) -> String {let temp = h.name.clone() + "正在战斗中....";println!("{}", temp);temp.to_string()
}
//这个方法要返回实现Debug特质的类型
async fn run(h: &Hero) -> String {let r = fight(&h).await;println!("{}", r);r
}

 

五、小结

  顺便也看了一些其它的资料。

  1. 创建异步函数的方式:函数(代码块)前加async,在函数体内添加await。 例外情况:不能把main标记为async
  2. 异步函数可以采用rust现有的两个异步运行时来运行:tokio或者async-std。似乎没有更多选择,此外为什么又那么多运行时,难道这个不应该是rust核心库的功能吗
  3. 异步的底层实现可能不一定是并发,也可能是并行,要看情况而定
  4. async函数默认返回的是 Future<Output = ()>。奇怪的语法又出现了,rust不要求你把返回结果显示地定义为Future。看第一个实例的page_title函数
    • 希望rust少一些这种默认的东西
    • 少一些故意和其它语言不同的东西
    • 此外,我也好奇,如果特意把返回类型写成Future会怎么样?
  5.  看了这些内容,距离异步编程还差99%

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/870184.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

介绍5种从resources获取inputStream的方法

@Component @Slf4j public class TestFileService {@Autowiredprivate ResourceLoader resourceLoader;@PostConstructpublic void testInputStream() throws IOException {// 5种从resources获取inputStream的方法// 在大多数情况下,推荐使用ResourceLoader或ClassPathResour…

开发一个篮球共享计分器小程序

篮球共享计分器,实现多人实时共享记录比赛,提供个人/团队数据和表现的统计数据,提供单机版/共享版/私密版三种模式记录比赛,提供精简/精准版模式选择,保存历史比赛数据,可用于文字直播。序言作为一名篮球爱好者的程序员,在使用目前市面篮球计分器时,总觉得用的不顺手,…

飞机电气系统技术分析:数字样机技术引领创新

现代飞机正向着更安全、环保和经济的方向发展,飞机系统的设计日益复杂,对各子系统的性能和可靠性也提出了更高要求。作为飞机的重要组成部分,电气系统(Electrical System,ES)不仅负责为各类机载设备提供稳定的电力支持,还在飞行控制、导航、通讯以及乘客舒适性等方面发挥…

Go操作MongoDB

NoSQL泛指非关系型数据库,如mongo,redis,HBase。 mongo使用高效的二进制数据存储,文件存储格式为 BSON ( 一种json的扩展,比json性能更好,功能更强大)。 MySQL中表的概念在mongo里叫集合(collection), MySQL中行的概念在mongo中叫文档(document),一个文档看上去像一个j…

2025年实战技巧!如何通过项目管理助力产品经理实现产品目标?

在当今竞争激烈的商业环境中,产品经理不仅要负责产品的整体规划和设计,还需要确保项目能够按时、按质、按预算完成。这就需要产品经理具备出色的项目管理能力。本文将深入探讨如何通过项目管理助力产品经理实现产品目标,并提供2025年的实战技巧。引言 随着市场的不断变化和技…

Polygon-funky

E. Polygon 给定一个数 n,生成一个 nn 的一个全为 0 的初始矩阵,矩阵上方和左方均有一排炮台,矩阵的下边和右边是边界 炮台可以发射子弹,子弹只能直线行走,且遇到边界后会停止,遇到一个停止的子弹也会停止,子弹停止后的坐标里面的值记为 1 在任何时候,都不会有超过一门…

2025四款简单好用的电脑便签提醒软件推荐

进入2025年,越来越多的打工人需要在电脑上使用一款桌面便签或日程提醒软件,随时记录和管理工作事项,能够帮助我们高效整理思绪,确保重要事务不被遗漏。 今天给大家介绍四款简单又好用的电脑便签或日程提醒软件,总有一款是适合你的! 一、Win系统便笺 Windows操作系统自带的…

本次小论文minor revision中的知识积累

可以发邮件向编辑申请延期返修截止日期 https://cn.service.elsevier.com/app/answers/detail/a_id/29653/c/10595/supporthub/publishing/role/作者/ https://zhuanlan.zhihu.com/p/577324425申请邮件模板:如何在Editorial Manager系统中提交修改稿?【爱思唯尔Editorial Man…

多通道传感器接入集中控制频率温度 传感器集线器带来更多方便

多通道传感器接入集中控制频率温度 传感器集线器带来更多方便现场传感器太多,编号容易混乱?传感器集线器可以将多路传感器轮流切换到单一接口,为现场提供更多方便。操作简便直观,使用一个百位拨动开关和两个旋转开关(十位和个位)自由切换到任意传感器。 传感器通道多,最…

实战指南:优化采购流程,实现高效采购管理

优化采购流程需要从多个方面入手,包括明确采购需求、加强供商管理、优化采购谈判与合同签订、加强采购执行与跟踪、提高质量控制与验收水平、进行成本分析与优化、加强人员培训与发展以及注重合规与风险管理。通过这些措施的实施,可以显著提高采购效率和质量,降低采购成本,…

Lableview 标签软件 | LABELVIEW 条形码标签软件

Lableview 标签软件 | LABELVIEW 条形码标签软件Lableview 专业顾问 手机|微信:13928851814值得您信赖的条形码标签软件稳健可靠的条形码标签创建与集成简单的数据库连接易于使用的界面和提供便利的向导100 多种条形码符号体系可自定义的打印界面变量选用表增加了灵活性LABE…

原生JS实现一个日期选择器(DatePicker)组件

这是通过原生HTML/CSS/JavaScript完成一个日期选择器(datepicker)组件,一个纯手搓的组件的开发。主要包括datepicker静态结构的编写、日历数据的计划获取、组件的渲染以及组件事件的处理。 根据调用时的时间格式参数,可以控制短日期格式或长日期格式。实现效果(短日期格式…