You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

主线程中额外的println为何导致Rust Tokio多线程执行结果差异?

问题本质:主线程退出速度导致Tokio任务执行差异

这是Tokio运行时的核心行为导致的,具体原因如下:

  • Tokio多线程运行时的终止规则:当启动Tokio运行时的主线程结束时,Tokio会立刻终止所有未完成的异步任务,不会等待它们执行完毕。
  • 加println!的效果:println!是同步阻塞操作,它会让主线程停留足够长的时间,给Tokio运行时留出调度并执行完所有10个任务的窗口,所以所有任务都能跑完。
  • 去掉println!的效果:主线程在创建完所有任务后会快速退出,此时Tokio运行时还没来得及把所有任务调度到线程上执行,就随着主线程的退出被终止了,因此只有少数已经被调度执行的任务能完成。

解决方案:显式等待所有任务完成

要确保所有异步任务都执行完毕,必须在主线程中显式等待所有任务的JoinHandle,常用两种方式:

1. 使用join_all等待动态任务列表

如果任务是动态创建的(比如循环生成),可以用futures::future::join_all收集并等待所有任务:

use tokio;
use futures::future::join_all;

#[tokio::main]
async fn main() {
    let mut task_handles = Vec::new();
    for task_id in 0..10 {
        task_handles.push(tokio::spawn(async move {
            println!("任务 {} 执行完成", task_id);
        }));
    }
    // 等待所有任务执行完毕
    join_all(task_handles).await;
}

2. 使用join!等待固定数量任务

如果任务数量固定,可以直接用tokio::join!逐个等待:

use tokio;

#[tokio::main]
async fn main() {
    let handle1 = tokio::spawn(async { println!("任务1执行") });
    let handle2 = tokio::spawn(async { println!("任务2执行") });
    // ... 其他任务
    let handle10 = tokio::spawn(async { println!("任务10执行") });
    
    // 等待所有任务完成
    tokio::join!(handle1, handle2, handle10);
}

这样不管主线程有没有println!,所有任务都会被执行完毕,因为主线程会一直等待到所有任务结束才退出。

内容的提问来源于stack exchange,提问作者Saber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:55:04