Rust : tokio中select!

关于tokio的select宏,有不少的用途。包括超时和竞态选择等。

关于select宏需要关注,相关的异步条件,会同时执行,只是当有一个最早完成时,会执行"抛弃"和"对应"策略。

说明:对本文以下素材的来源表示感谢!

bash 复制代码
 https://zhuanlan.zhihu.com/p/14498925766

select宏分支匹配的定义:

bash 复制代码
<pattern> = <async expression> => <handler>

pattern当有返回值且需要处理,往往用val、Some(val)待形式表示,如果没有返回值或返回值不需处理,往往用"_"来表示。

而async expression部分,就是我们所指的condition_action部分。而handler部分就是分支对应的"后续任务"部分。

一、toml

bash 复制代码
[dependencies]
tokio = { version = "1.42.0",  features = ["full"] }

二、main.rs

说明:

condition_action为异步"条件任务";在后面的是"后续任务"。是否执行"后续任务"的前提是,哪个条件任务是最早完成。但这个选择是通过异步同时执行所有的"条件任务"PK出来的。

举个例子,可能更清楚:

比如学校某班级有3位同学,测试其运动水平高低,并决定水平最高的人可以参加学校运动会比赛(篮球或足球比赛,这个举例不一定合理)。假设设定测试条件任务是跑10000米(即condition_action),那么,我们可以让3位同学同时跑,首先冲过终点的人,马上去参加比赛("后续任务")。

当3位同学中,只要有人首先冲过终点(condition_action结束),就让他去代表参加比赛(执行后续任务,篮球或足球由其决定)。很显然,其它的人就不用跑了,可以停下来了,即被"抛弃"了,更不需要去参赛。

bash 复制代码
use tokio::time;

async fn conditon_action(s: String) -> String{
    println!("\t 执行条件任务 {} 开始.", s);
    time::sleep(time::Duration::from_secs(1)).await;
    println!("\t 执行条件任务 {} 结束! 后续执行 => {},其它任务不执行!", s,s);
    s
}

#[tokio::main]
async fn main() {
    for i in 0..3 {
        println!("Round {}:", i);
        time::sleep(time::Duration::from_secs(2)).await;
        // 注意:(1) select!会同时执行_A和_B两个任务;
        // (2)但是只会选择_A与_B中最先完成的任务对应的任务来执行后续的任务;
        // (3)同时,_A与_B中没有被执行完的部分,后续不执行。具体表现在condition_action函中有"开始"没有"结束".

        tokio::select! {
            val = conditon_action(i.to_string()+"_A") => {
                println!("\t 执行后续任务{} 开始.", val);
                time::sleep(time::Duration::from_secs(2)).await;
                println!("\t 执行后续任务{} 结束.", val);
            },
            val = conditon_action(i.to_string()+"_B") => {
                println!("\t 执行后续任务{} 开始.", val);
                time::sleep(time::Duration::from_secs(2)).await;
                println!("\t 执行后续任务{} 结束.", val);
            }
        }
    }
}

输出:

bash 复制代码
Round 0:
         执行条件任务 0_B 开始.
         执行条件任务 0_A 开始.
         执行条件任务 0_A 结束! 后续执行 => 0_A,其它任务不执行!
         执行后续任务0_A 开始.
         执行后续任务0_A 结束.
Round 1:
         执行条件任务 1_B 开始.
         执行条件任务 1_A 开始.
         执行条件任务 1_B 结束! 后续执行 => 1_B,其它任务不执行!
         执行后续任务1_B 开始.
         执行后续任务1_B 结束.
Round 2:
         执行条件任务 2_A 开始.
         执行条件任务 2_B 开始.
         执行条件任务 2_A 结束! 后续执行 => 2_A,其它任务不执行!
         执行后续任务2_A 开始.
         执行后续任务2_A 结束.

解读:

对于round0:

1、A和B条件任务均执行,但B任务提前完成,此时A任务未完成部分"抛弃"

2、执行后续B任务

对于round1:

1、A和B条件任务均执行,但A任务提前完成,此时B任务未完成部分"抛弃"

2、执行后续A任务.

对于round2:

1、A和B条件任务均执行,但A任务提前完成,此时B任务未完成部分"抛弃"

2、执行后续A任务.

从上面可以清晰看到,tokio的select!中"抛弃"和"后续执行"策略。

相关推荐
武子康13 分钟前
大数据-132 Flink SQL 实战入门 | 3 分钟跑通 Table API + SQL 含 toChangelogStream 新写法
大数据·后端·flink
jarreyer18 分钟前
python离线包安装方法总结
开发语言·python
李辰洋20 分钟前
go tools安装
开发语言·后端·golang
wanfeng_0925 分钟前
go lang
开发语言·后端·golang
绛洞花主敏明27 分钟前
go build -tags的其他用法
开发语言·后端·golang
ByteCraze32 分钟前
秋招被问到的常见问题
开发语言·javascript·原型模式
码银35 分钟前
【python】基于 生活方式与健康数据预测数据集(Lifestyle and Health Risk Prediction)的可视化练习,附数据集源文件。
开发语言·python·生活
Pluchon37 分钟前
硅基计划5.0 MySQL 叁 E-R关系图&联合/多表查询&三大连接&子查询&合并查询
开发语言·数据库·学习·mysql
kyle~44 分钟前
C++---嵌套类型(Nested Types)封装与泛型的基石
开发语言·c++·算法
sali-tec1 小时前
C# 基于halcon的视觉工作流-章48-短路断路
开发语言·图像处理·人工智能·算法·计算机视觉