Concurrency lets multiple tasks make progress during overlapping periods; it does not require them to execute simultaneously. In async Rust, a task waiting for I/O can make room for other work. This is especially useful when waiting takes much longer than processing the result. section 8.0 section 8.2
Choose how tasks overlap:
- Use `tokio::join!` or `futures::future::join_all()` to drive multiple futures concurrently. Use `tokio::select!` to wait on multiple concurrent branches. section 8.5
- Use `tokio::task::spawn()` to let Tokio schedule a task on a worker thread. It permits parallel execution but does not guarantee it; a single-worker runtime still runs its tasks on one thread. section 8.5
Test 1: Run 2 async tasks sequentially Entering sleep_1s_blocking(Task 1) Returning from sleep_1s_blocking(Task 1) Entering sleep_1s_blocking(Task 2) Returning from sleep_1s_blocking(Task 2) Test 2: Run 2 async tasks concurrently (same thread) Entering sleep_1s_blocking(Task 3) Returning from sleep_1s_blocking(Task 3) Entering sleep_1s_blocking(Task 4) Returning from sleep_1s_blocking(Task 4) Test 3: Run 2 async tasks in parallel Entering sleep_1s_blocking(Task 5) #1 Entering sleep_1s_blocking(Task 6) Returning from sleep_1s_blocking(Task 5) Returning from sleep_1s_blocking(Task 6)
Compare the printed order: with blocking sleep, joined tasks finish one after the other, while spawned tasks can enter before either returns. section 8.5
async fn sleep_1s_nonblocking(task: &str) {
use tokio::time::{sleep, Duration};
println!("Entering sleep_1s_nonblocking({task})");
sleep(Duration::from_secs(1)).await;
println!("Returning from sleep_1s_nonblocking({task})");
}
Replace blocking `thread::sleep` with `tokio::time::sleep(...).await` so waiting does not prevent another joined task from progressing. section 8.5
Use async when concurrency is needed, particularly for many I/O operations or network requests. Prefer simpler synchronous code for a CLI doing sequential file I/O or a client making only a few sequential requests. Plan ahead: adding async later is harder, while Tokio adds some overhead to otherwise sequential work. section 8.8






















