When I am running the below code with flavor = "current_thread", I am seeing output only from first task and not the other. My understanding was that even in a single threaded execution, async code can be run concurrently. What am I missing?
use std::{
thread,
time::{Duration, SystemTime},
};
#[tokio::main(flavor = "current_thread")]
async fn main() {
let handle_1 = tokio::spawn(async move {
loop {
println!("{:?} Hello from 1", SystemTime::now());
thread::sleep(Duration::from_millis(2000))
}
});
let handle_2 = tokio::spawn(async move {
loop {
println!("{:?} Hello from 2", SystemTime::now());
thread::sleep(Duration::from_millis(5000))
}
});
handle_1.await.unwrap();
handle_2.await.unwrap();
}
Output
SystemTime { tv_sec: 1719896401, tv_nsec: 253252588 } Hello from 1
SystemTime { tv_sec: 1719896403, tv_nsec: 253411156 } Hello from 1
SystemTime { tv_sec: 1719896405, tv_nsec: 253504834 } Hello from 1
SystemTime { tv_sec: 1719896407, tv_nsec: 253627641 } Hello from 1
SystemTime { tv_sec: 1719896409, tv_nsec: 253785910 } Hello from 1
SystemTime { tv_sec: 1719896411, tv_nsec: 254074102 } Hello from 1
SystemTime { tv_sec: 1719896413, tv_nsec: 254410243 } Hello from 1
SystemTime { tv_sec: 1719896415, tv_nsec: 254574553 } Hello from 1
SystemTime { tv_sec: 1719896417, tv_nsec: 254955748 } Hello from 1
SystemTime { tv_sec: 1719896419, tv_nsec: 258449707 } Hello from 1
SystemTime { tv_sec: 1719896421, tv_nsec: 258703255 } Hello from 1
SystemTime { tv_sec: 1719896423, tv_nsec: 258839315 } Hello from 1
SystemTime { tv_sec: 1719896425, tv_nsec: 259088384 } Hello from 1
SystemTime { tv_sec: 1719896427, tv_nsec: 259232553 } Hello from 1
SystemTime { tv_sec: 1719896429, tv_nsec: 260017836 } Hello from 1
Only one task ever runs, because you are blocking entire thread. Use tokio::time::sleep to communicate to your runtime that task should yield whilst sleeping.
use std::{
time::{Duration, SystemTime},
};
#[tokio::main(flavor = "current_thread")]
async fn main() {
let handle_1 = tokio::spawn(async move {
loop {
println!("{:?} Hello from 1", SystemTime::now());
tokio::time::sleep(Duration::from_millis(2000)).await;
}
});
let handle_2 = tokio::spawn(async move {
loop {
println!("{:?} Hello from 2", SystemTime::now());
tokio::time::sleep(Duration::from_millis(5000)).await;
}
});
handle_1.await.unwrap();
handle_2.await.unwrap();
}
In general you shouldn't use blocking code inside async
. You can cause all sorts of deadlocks that way. If you need to use blocking code in tokio, use tokio::task::spawn_blocking, which will run provided closure on the another threadpool, dedicated to blocking tasks.