A thread is an independently schedulable path of execution within a process. If one thread waits for a blocking operation, another can continue working. This makes threads useful when independent tasks would otherwise wait for each other. section 10.1
Run two independent operations
Suppose two functions simulate file reads by sleeping for four and two seconds. Calling them sequentially takes about six seconds. Spawn each function on a separate operating-system thread, then join both thread handles before main returns. The waits can now overlap, so the run takes less than six seconds. section 10.2
use std::thread;
use std::thread::sleep;
use std::time::Duration;
fn main() {
println!("Hello before reading file!");
let handle1 = thread::spawn(|| { #1
let file1_contents = read_from_file1();
println!("{:?}", file1_contents);
});
let handle2 = thread::spawn(|| { #2
let file2_contents = read_from_file2();
println!("{:?}", file2_contents);
});
handle1.join().unwrap(); #3
handle2.join().unwrap(); #4
}
// function that simulates reading from a file
fn read_from_file1() -> String {
sleep(Duration::new(4, –));
String::from("Hello, there from file 1")
}
// function that simulates reading from a file
fn read_from_file2() -> String {
sleep(Duration::new(2, –));
String::from("Hello, there from file 2")
}
The listing shows std::thread::spawn creating two threads and join waiting for both to finish. section 10.2
Threads are not the only way to handle waiting work. An async runtime such as Tokio can schedule another task when a task waits for I/O, potentially processing concurrent tasks on a single thread. The distinction is between spawning operating-system threads and scheduling async tasks. section 10.1 section 10.2











