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!中"抛弃"和"后续执行"策略。

相关推荐
tan180°8 分钟前
Linux进程信号处理(26)
linux·c++·vscode·后端·信号处理
邹诗钰-电子信息工程22 分钟前
嵌入式自学第二十一天(5.14)
java·开发语言·算法
有梦想的攻城狮30 分钟前
spring中的@MapperScan注解详解
java·后端·spring·mapperscan
恋猫de小郭43 分钟前
如何查看项目是否支持最新 Android 16K Page Size 一文汇总
android·开发语言·javascript·kotlin
柚个朵朵1 小时前
Spring的Validation,这是一套基于注解的权限校验框架
java·后端·spring
于壮士hoho1 小时前
Python | Dashboard制作
开发语言·python
Asus.Blogs2 小时前
为什么go语言中返回的指针类型,不需要用*取值(解引用),就可以直接赋值呢?
开发语言·后端·golang
青瓦梦滋2 小时前
【语法】C++的多态
开发语言·c++
C_V_Better3 小时前
Java Spring Boot 控制器中处理用户数据详解
java·开发语言·spring boot·后端·spring
胡子洲3 小时前
Spring Boot 应用中实现基本的 SSE 功能
java·spring boot·后端