I am trying to understand how tokio
runtime works, i created two runtimes(on purpose) using #[tokio::main]
macro, the first should executes function a()
and the second executes function b()
.
I am assuming that they should be both printing "im awake A"
and "im awake B"
simultaniosuly forever (since they are calling a function that has a loop async_task
), however that is not the case, it only prints "im awake A".
since each runtime has its own thread pool; why they are not running in parallel?
use std::thread;
fn main() {
a();
b();
}
#[tokio::main]
async fn a() {
tokio::spawn(async move { async_task("A".to_string()).await });
}
pub async fn async_task(msg: String) {
loop {
thread::sleep(std::time::Duration::from_millis(1000));
println!("im awake {}", msg);
}
}
#[tokio::main]
async fn b() {
tokio::spawn(async move { async_task("B".to_string()).await });
}
Calling a();
from the synchronous main
function will block until a()
finishes. Check out the documentation here: https://docs.rs/tokio/1.2.0/tokio/attr.main.html
#[tokio::main] async fn main() { println!("Hello world"); }
Equivalent code not using #[tokio::main]
fn main() { tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap() .block_on(async { println!("Hello world"); }) }
To get your example to work, main()
could also spawn 2 threads that run a, b and wait for them to finish:
fn main() {
let t1 = thread::spawn(|| {
a();
});
let t2 = thread::spawn(|| {
b();
});
t1.join().unwrap();
t2.join().unwrap();
}
EDIT:
Note that a()
and b()
also do not need to use tokio::spawn
as they're already executing in their own async runtime.
#[tokio::main]
async fn a() -> Result<(), JoinError> {
async_task("A".to_string()).await
}
#[tokio::main]
async fn b() {
async_task("B".to_string()).await
}
If you use tokio::spawn
in a
and b
, you would need to await the spawned future, but tokio::spawn(task.await).await
is basically the same as just doing task.await
.