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

相关推荐
论迹11 分钟前
【JavaEE】-- 多线程(初阶)2
java·开发语言·java-ee
+72021 分钟前
如何在java中用httpclient实现rpc post 请求
java·开发语言·rpc
ybq1951334543123 分钟前
javaEE-SpringBoot日志
java·spring boot·后端
web_1553427465629 分钟前
性能巅峰对决:Rust vs C++ —— 速度、安全与权衡的艺术
c++·算法·rust
weixin_5025398529 分钟前
rust学习笔记5-所有权机制
笔记·学习·rust
学习两年半的Javaer30 分钟前
Rust语言基础知识详解【一】
开发语言·rust
PyAIGCMaster30 分钟前
50周学习go语言:第四周 函数与错误处理深度解析
开发语言·学习·golang
全栈开发圈31 分钟前
新书速览|Rust汽车电子开发实践
开发语言·rust·汽车
m0_7482382732 分钟前
项目升级Sass版本或升级Element Plus版本遇到的问题
前端·rust·sass
PyAIGCMaster33 分钟前
第二周补充:Go语言中&取地址符与fmt函数详解
开发语言·后端·golang