说到异步运行时,很多人只会 #[tokio::main]。这篇自己写一个最小的执行器,把「任务队列、waker、poll 循环、定时器唤醒」这四个部件都亲手实现并跑通,再用它证明为什么异步任务里不能阻塞。
编译:成功
运行(退出码 0):
[ 0 ms] 任务 A 开始(同一线程: true)
[ 0 ms] 任务 B 开始(同一线程: true)
[ 0 ms] 任务 C 开始(同一线程: true)
[ 50 ms] 任务 B 睡了 50 ms,醒来结束
[100 ms] 任务 C 睡了 100 ms,醒来结束
[150 ms] 任务 A 睡了 150 ms,醒来结束
总耗时约 150 ms(最长的任务 150 ms,而不是 150 + 50 + 100 = 300 ms);executor 一共 poll 了 6 次Future 与 Poll 的基础见Future 与 Poll。
编译:成功
运行(退出码 0):
任务开始
poll x → Pending,注册 waker(来自 "main")
定时器线程 wake()
任务被再次 poll,继续执行并结束
executor 退出,共 poll 2 次Waker 的细节见Waker 唤醒机制。
编译:成功
运行(退出码 0):
[ 0 ms] 阻塞任务开始 thread::sleep(200)
[200 ms] 阻塞任务结束
[200 ms] 异步任务开始 sleep(20).await(期望 20 ms 后醒来)
[220 ms] 异步任务醒来更多见阻塞代码混入异步任务。
tokio current_thread:[150, 50, 100] 总耗时约 150 ms
tokio 的调度见Tokio 任务调度。tokio 1.x 从 crates.io 下载(需要联网)。