Hi guys, I'm learning tokio recently, but I encountered some incomprehensible problems, such as the sequential execution of code in tokio::spawn.
#[tokio::test]
async fn test_tokio() {
use std::thread;
use std::time::Duration;
let r = tokio::spawn(async move {
for i in (1..10).rev() {
println!("hi number {} from the spawned thread!", i);
// let _ = tokio::time::sleep(tokio::time::Duration::from_secs(i)).await;
thread::sleep(Duration::from_secs(i));
println!("bye number {} from the spawned thread!", i);
}
});
let _ = tokio::join!(r);
// let _ = r.await;
for i in 1..5 {
println!("hi number {} from the main thread!", i);
let _ = tokio::time::sleep(tokio::time::Duration::from_millis(1));
}
}
What I expect is that the functions in spawn are executed at the same time, but this code is indeed executed one by one. The next one will not start until the previous one is executed, so why is this?
You are only spawning a single task and performing a normal, sequential loop inside it. You are not spawning multiple tasks. And a simple for loop does not loop in parallel.
(Oh, and you are also blocking inside the spawned task by using thread::sleep, which means that even if you had multiple tasks, you would block the runtime in each of them anyway.)
#[tokio::test]
async fn test_tokio() {
use std::thread;
use std::time::Duration;
let mut handles = Vec::new();
for i in 1..10 {
let r = tokio::spawn(async move {
println!("hi number {} from the spawned thread!", i);
// let _ = tokio::time::sleep(tokio::time::Duration::from_secs(i)).await;
// thread::sleep(Duration::from_secs(1));
println!("bye number {} from the spawned thread!", i);
});
handles.push(r);
}
// let _ = tokio::join!(r);
for i in handles {
i.await.unwrap();
}
}
But they still run one by one:
hi number 1 from the spawned thread!
bye number 1 from the spawned thread!
hi number 2 from the spawned thread!
bye number 2 from the spawned thread!
hi number 3 from the spawned thread!
bye number 3 from the spawned thread!
hi number 4 from the spawned thread!
bye number 4 from the spawned thread!
hi number 5 from the spawned thread!
bye number 5 from the spawned thread!
hi number 6 from the spawned thread!
bye number 6 from the spawned thread!
hi number 7 from the spawned thread!
bye number 7 from the spawned thread!
hi number 8 from the spawned thread!
bye number 8 from the spawned thread!
hi number 9 from the spawned thread!
bye number 9 from the spawned thread!
No, they are running in parallel. For example, I got this:
hi number 1 from the spawned thread!
bye number 1 from the spawned thread!
hi number 4 from the spawned thread!
bye number 4 from the spawned thread!
hi number 5 from the spawned thread!
bye number 5 from the spawned thread!
hi number 6 from the spawned thread!
bye number 6 from the spawned thread!
hi number 7 from the spawned thread!
bye number 7 from the spawned thread!
hi number 8 from the spawned thread!
bye number 8 from the spawned thread!
hi number 9 from the spawned thread!
bye number 9 from the spawned thread!
hi number 2 from the spawned thread!
bye number 2 from the spawned thread!
hi number 3 from the spawned thread!
bye number 3 from the spawned thread!
Notice the ordering. The fact that they're not interleaved is just because the two printlns happen so close to each other. They will sometimes be interleaved, even if it is rare.