select! 与并发 futures
学习目标
- 掌握
tokio::select!
- 理解分支取消语义
- 掌握超时和竞态模式
核心概念
基本 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 | 超时包装 |