Day 2:tokio::spawn 與任務並行
學習目標
- 用 tokio::spawn 建立並行任務
- 用 JoinHandle 等待並收集
- 理解 join! 與 spawn 的差別
今日重點
tokio::spawn
use tokio::time::{sleep, Duration};
async fn task(id: u32) {
println!("Task {} started", id);
sleep(Duration::from_millis(100 * id as u64)).await;
println!("Task {} completed", id);
}
#[tokio::main]
async fn main() {
// spawn:立即開始,不需等
let h1 = tokio::spawn(task(1));
let h2 = tokio::spawn(task(2));
let h3 = tokio::spawn(task(3));
// 等待全部完成(join! 等 JoinHandle)
let _ = tokio::join!(h1, h2, h3);
}
join! vs spawn
|
join! |
spawn |
| 型別 |
相同型別、可巢狀 |
不同任務、回傳 JoinHandle |
| 數量 |
固定(寫死) |
任意、動態 |
| 結果 |
直接拿回傳值 |
handle.await / join |
| 用途 |
少數已知任務 |
大量或動態工作 |
spawn 回傳值
#[tokio::main]
async fn main() {
let handle = tokio::spawn(async { 42 });
let result: Result<i32, tokio::task::JoinError> = handle.await;
println!("{:?}", result); // Ok(42)
}
練習
async fn square(n: i32) -> i32 {
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
n * n
}
#[tokio::main]
async fn main() {
// 開 5 個 spawn,各算平方,收集結果
let mut handles = vec![];
for i in 1..=5 {
handles.push(tokio::spawn(square(i)));
}
for h in handles {
println!("{}", h.await.unwrap());
}
}
自我檢查
深入連結