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

相关推荐
warpdrivelabs1 小时前
Codex 开源 harness 全面了解
开发语言·人工智能
丰锋ff5 小时前
基于 Qt 的智能门禁系统(二)
开发语言·qt
fpcc5 小时前
跟我学C++中级篇——编译期的条件选择
开发语言·c++
SomeB1oody5 小时前
【RustyML入门】6.3. 并行归约
开发语言·后端·机器学习·rust·教程
Profile排查笔记6 小时前
指纹浏览器哪个好?从 Profile、代理、权限和自动化能力判断是否适合
前端·人工智能·后端·自动化
用户938515635077 小时前
用 AI 结对编程从 0 搭一个"单词后台管理系统":Next.js + Supabase + Drizzle + shadcn/ui 全记录
后端·postgresql·next.js
mqiqe7 小时前
AgentScope Java 2.0 协议集成全景解析:A2A、AG-UI、Agent Protocol 三大开放协议实战指南
java·开发语言·ui
lzhdim7 小时前
12、JavaScript常见的内存泄露问题 - JavaScript学习系列文章
开发语言·前端·javascript·学习·ecmascript
脉动数据行情7 小时前
Java 实现台股 TWSE/TPEx 行情采集(个股 + K 线)
java·开发语言·twse·tpex·台股
爱学习的小邓同学7 小时前
Golang --- (1)第一个Golang程序
开发语言·后端·golang