我不确定 tokio
是否类似于JavaScript中的事件循环,也是一种非阻塞运行时,或者它是否可以用类似的方式工作。在我的理解中,tokio
是一个用于Rust中的futures的运行时。因此,它必须实现某种用户级线程或任务,这可以通过事件循环(至少部分地)来调度新任务。
让我们看一下以下JavaScript代码:
console.log('hello1');
setTimeout(() => console.log('hello2'), 0);
console.log('hello3');
setTimeout(() => console.log('hello4'), 0);
console.log('hello5');
输出结果将会是:
hello1
hello3
hello5
hello2
hello4
我该如何在tokio中实现这个?tokio整体上是这样工作的吗?我尝试了以下代码
async fn set_timeout(f: impl Fn(), ms: u64) {
tokio::time::sleep(tokio::time::Duration::from_millis(ms)).await;
f()
}
#[tokio::main]
async fn main() {
println!("hello1");
tokio::spawn(async {set_timeout(|| println!("hello2"), 0)}).await;
println!("hello3");
tokio::spawn(async {set_timeout(|| println!("hello4"), 0)}).await;
println!("hello5");
}
输出仅为
hello1
hello3
hello5
如果我更改代码为
println!("hello1");
tokio::spawn(async {set_timeout(|| println!("hello2"), 0)}.await).await;
println!("hello3");
tokio::spawn(async {set_timeout(|| println!("hello4"), 0)}.await).await;
println!("hello5");
输出为
hello1
hello2
hello3
hello4
hello5
但这样做我就不太明白整个异步/等待/未来功能的意义了,因为我的“异步”set_timeout任务实际上会阻塞其他println语句。
main
结束时,你必须等待所有的操作完成。Tokio 不会为你处理 - 当main
退出时,事件循环会立即关闭。 - Cerberus