📖 Scenario: You are building a simple Rust program that uses threads to run tasks in parallel. This is useful when you want your program to do multiple things at the same time, like cooking and cleaning in a kitchen.
🎯 Goal: Create a Rust program that starts a new thread to print a message, while the main thread prints another message. This will show how threads work together.
📋 What You'll Learn
Create a new thread using std::thread::spawn
Use a closure to define the thread's task
Print a message from the new thread
Print a message from the main thread
Wait for the new thread to finish using join
💡 Why This Matters
🌍 Real World
Threads let programs do many things at once, like downloading files while showing a progress bar.
💼 Career
Understanding threads is important for building fast and responsive software in many jobs, including systems programming and web servers.
Progress0 / 4 steps
1
Create a new thread
Write code to create a new thread using std::thread::spawn that runs a closure printing "Hello from the new thread!". Store the thread handle in a variable called handle.
Rust
Hint
Use thread::spawn with a closure || { ... } to create the thread.
2
Print from the main thread
Add a line to print "Hello from the main thread!" in the main thread after creating the new thread.
Rust
Hint
Use println! to print the message in the main thread.
3
Wait for the new thread to finish
Call handle.join().unwrap() to wait for the new thread to finish before the program ends.
Rust
Hint
Use join() on the thread handle to wait for the thread to finish.
4
Print the final output
Run the program and print the output messages from both threads.
Rust
Hint
Run the program to see both messages printed. The order may vary because threads run in parallel.
Practice
(1/5)
1. What does thread::spawn do in Rust?
easy
A. It stops all threads immediately.
B. It pauses the current thread for a set time.
C. It creates a new thread to run code concurrently.
D. It merges two threads into one.
Solution
Step 1: Understand the purpose of thread::spawn
This function is used to start a new thread that runs code independently from the main thread.
Step 2: Compare options with the function's role
Only "It creates a new thread to run code concurrently." correctly describes creating a new thread. Other options describe unrelated actions.
Final Answer:
It creates a new thread to run code concurrently. -> Option C
Quick Check:
thread::spawn creates threads [OK]
Hint: Remember: spawn means start a new thread [OK]
Common Mistakes:
Confusing spawn with pausing or stopping threads
Thinking spawn merges threads
Assuming spawn waits for thread completion
2. Which of the following is the correct syntax to create a new thread in Rust?
easy
A. let handle = thread::spawn(|| { println!("Hello"); });
B. let handle = spawn::thread(|| { println!("Hello"); });
C. thread.spawn(|| println!("Hello"));
D. thread::create(|| { println!("Hello"); });
Solution
Step 1: Recall the correct module and function
The correct function to create a thread is thread::spawn from the std::thread module.
Step 2: Check syntax correctness
let handle = thread::spawn(|| { println!("Hello"); }); uses the correct syntax: thread::spawn(|| { ... }). Other options use wrong module names or functions.
Final Answer:
let handle = thread::spawn(|| { println!("Hello"); }); -> Option A
Quick Check:
Correct syntax uses thread::spawn [OK]
Hint: Use thread::spawn with a closure to start threads [OK]
Common Mistakes:
Swapping module and function names
Missing double colons (::) in path
Using non-existent functions like create()
3. What will be the output of this Rust code?
use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("Inside thread");
});
println!("Outside thread");
handle.join().unwrap();
}
medium
A. Inside thread
Outside thread
B. Outside thread
Inside thread
C. Only Inside thread
D. Only Outside thread
Solution
Step 1: Understand thread execution order
The main thread prints "Outside thread" immediately. The spawned thread runs concurrently and prints "Inside thread".
Step 2: Consider join() effect
The join() waits for the spawned thread to finish, but does not change the order of prints already done.
Final Answer:
Outside thread
Inside thread -> Option B
Quick Check:
Main prints first, spawned thread prints after [OK]
Hint: Main thread prints first, spawned thread runs concurrently [OK]
Common Mistakes:
Assuming spawned thread always prints first
Ignoring that join() waits but doesn't reorder prints
Thinking only one print appears
4. Identify the error in this Rust code that creates a thread:
use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("Hello from thread");
});
handle.join();
}
medium
A. println! macro cannot be used inside threads.
B. thread::spawn requires a named function, not a closure.
C. join() should be called before thread::spawn.
D. Missing call to unwrap() on join() result.
Solution
Step 1: Check join() usage
The join() method returns a Result that should be handled, usually by calling unwrap() to catch panics.
Step 2: Verify other statements
The other options are incorrect: println! macro works inside threads, thread::spawn accepts closures, and join() is called after spawn.
Final Answer:
Missing call to unwrap() on join() result. -> Option D
Quick Check:
Always unwrap join() result to handle errors [OK]
Hint: Always unwrap join() to handle thread errors [OK]
Common Mistakes:
Ignoring join()'s Result return
Thinking closures can't be used in spawn
Calling join() before spawn
5. You want to create 3 threads that each print their thread number (1, 2, 3). Which code correctly does this without data races?
use std::thread;
fn main() {
for i in 1..=3 {
thread::spawn(|| {
println!("Thread number: {}", i);
});
}
}
hard
A. Move i into closure: thread::spawn(move || { println!("Thread number: {}", i); });
B. Use thread::spawn(|| { println!("Thread number: {}", i); }); as is.
C. Declare i as static before loop.
D. Use thread::spawn(|| println!("Thread number: {}", i)); without move.
Solution
Step 1: Understand closure capturing in threads
The variable i changes each loop iteration. Without move, the closure captures i by reference, causing data races.
Step 2: Use move to capture i by value
Adding move moves the current value of i into the closure, making each thread print its own number safely.
Final Answer:
Move i into closure: thread::spawn(move || { println!("Thread number: {}", i); }); -> Option A
Quick Check:
Use move closures to capture loop variables safely [OK]
Hint: Use move closures to capture loop variables in threads [OK]
Common Mistakes:
Not using move causes all threads to print last i value
Trying to declare i as static (not allowed here)
Assuming closure captures by value without move
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.