A JoinHandle is the handle returned by std::thread::spawn. It represents a spawned thread and lets the program wait until that thread finishes. Without waiting, main may finish while worker threads are still running. section 11.6.1 section 11.7
Wait for several threads
Store each handle, start all the threads, then join them afterward: let mut join_handles = vec![]; for _ in 0..10 { let handle = std::thread::spawn(|| { println!("I am printing something"); }); join_handles.push(handle); } for handle in join_handles { handle.join().unwrap(); } Calling join() makes the current code wait for that thread. Keeping handles in a vector allows all ten threads to start before the program waits for them. section 11.6.2
fn main() {
let mut join_handles = vec![]; #1
for _ in 0..10 {
let handle = std::thread::spawn(|| {
println!("I am printing something");
});
join_handles.push(handle); #2
}
for handle in join_handles { #3
handle.join().unwrap();
}
}
Browse the complete multi-thread example that collects JoinHandles and joins them after spawning all workers. section 11.6.2
A JoinHandle also exposes the lifetime boundary between the spawning code and its worker:
- Calling join() inside the spawning loop waits before the next thread starts, so collecting handles first enables concurrent startup. section 11.6.2
- Closures passed to spawn may need move so they own captured values; the compiler recommends it when borrowed data might outlive its scope. section 11.6.2
