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());
    }
}

自我檢查

  • 會用 tokio::spawn 建立並行任務
  • 會 await JoinHandle 收集結果
  • 知道 join! vs spawn 的適用差別
  • 能開動態數量的任務

深入連結

  • tokio 官方文件(Tasks)