Limited concurrency for future execution (tokio)

How about something like this?

use tokio::time::{sleep, Duration};
use rand::{thread_rng, Rng};
use tokio::task::JoinSet;

#[tokio::main]
async fn main() {
    let max_concurrent = 2;
    let ids: Vec<u64> = (1..=10).into_iter().collect();
    let mut join_set = JoinSet::new();
    
    for id in ids {
        while join_set.len() >= max_concurrent {
            join_set.join_next().await.unwrap().unwrap();
        }
        join_set.spawn(my_bg_task(id));
    }
    
    println!("DONE SPAWNING");
    
    while let Some(output) = join_set.join_next().await {
        output.unwrap();
    }
    
    println!("ALL DONE");
}

async fn my_bg_task(id: u64) {
    let num: u64 = thread_rng().gen_range(10..200);
    println!("START id: {} with {}ms", id, num);
    sleep(Duration::from_millis(num)).await;
    println!("STOP id: {}", id);
}