Limit Async Concurrency with a Semaphore
Share a tokio semaphore across spawned tasks, hold a permit for each job, and collect every result with JoinSet.
Code
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::Semaphore;
use tokio::task::JoinSet;
use tokio::time::sleep;
#[tokio::main]
async fn main() {
let limit = Arc::new(Semaphore::new(2));
let mut tasks = JoinSet::new();
for id in 0..6 {
let permits = Arc::clone(&limit);
tasks.spawn(async move {
let _permit = permits.acquire_owned().await.expect("semaphore closed");
sleep(Duration::from_millis(30)).await;
id * id
});
}
let mut results = Vec::new();
while let Some(joined) = tasks.join_next().await {
results.push(joined.expect("task panicked"));
}
results.sort_unstable();
println!("{results:?}");
}
Report a problem with this exampleOpens a pre-filled issue on GitHub.