53·异步编程进阶

select! 与并发 futures

select! 与并发 futures

学习目标

  1. 掌握 tokio::select!
  2. 理解分支取消语义
  3. 掌握超时和竞态模式

核心概念

基本 select!

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    tokio::select! {
        _ = sleep(Duration::from_secs(1)) => {
            println!("sleep 1 先完成");
        }
        _ = sleep(Duration::from_secs(2)) => {
            println!("sleep 2 先完成");
        }
    }
    // 只执行第一个完成的分支,其他被取消
}

带返回值

use tokio::time::{sleep, Duration};

async fn fast() -> String { "fast".to_string() }
async fn slow() -> String { "slow".to_string() }

#[tokio::main]
async fn main() {
    let result = tokio::select! {
        val = fast() => val,
        val = slow() => val,
    };
    println!("结果: {}", result);
}

超时模式

use tokio::time::{timeout, Duration};

#[tokio::main]
async fn main() {
    match timeout(Duration::from_secs(1), long_operation()).await {
        Ok(result) => println!("完成: {}", result),
        Err(_) => println!("超时"),
    }
}

循环 select!

use tokio::sync::mpsc;
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    let (tx, mut rx) = mpsc::channel(32);

    tokio::spawn(async move {
        for i in 0..5 {
            tx.send(i).await.unwrap();
            sleep(Duration::from_millis(500)).await;
        }
    });

    loop {
        tokio::select! {
            Some(msg) = rx.recv() => {
                println!("收到: {}", msg);
            }
            _ = sleep(Duration::from_secs(3)) => {
                println!("超时,退出");
                break;
            }
        }
    }
}

小结

模式说明
select! { ... }等待第一个完成的分支
其他分支取消未完成的 future 被丢弃
timeout超时包装

练习编辑器

rust
Loading...