Multithreading: Doing Many Things at Once
In a standard Java program, code runs in a single "Thread" (the main thread). If one task takes a long time (like downloading a file or processing a heavy config), the whole program freezes. Multithreading allows you to spawn background workers to handle these tasks while the main program stays responsive.
1. Two Ways to Create a Thread
A. Extending the Thread Class
You create a subclass and override the run() method.
class MyWorker extends Thread {
public void run() {
System.out.println("Worker thread is running...");
}
}
// To start:
MyWorker t1 = new MyWorker();
t1.start(); // This spawns the new thread
B. Implementing the Runnable Interface (Recommended)
This is more flexible because your class can still extend another parent class (like a BaseController).
class MyTask implements Runnable {
public void run() {
System.out.println("Runnable task is running...");
}
}
// To start:
Thread t1 = new Thread(new MyTask());
t1.start();
2. Important Thread Methods
| Method | Description |
|---|---|
start() |
Starts the thread and calls run(). Never call run() directly! |
sleep(ms) |
Pauses the current thread for a specific time. |
join() |
Waits for a specific thread to finish before continuing. |
isAlive() |
Checks if the thread is still running. |
setPriority() |
Suggests to the CPU which thread is more important. |
3. The synchronized Keyword (Safety First)
When two threads try to change the same variable at the exact same time, you get a "Race Condition" (data corruption). We use synchronized to lock a method so only one thread can enter at a time.
class Counter {
int count = 0;
// Only one thread can increment at a time
public synchronized void increment() {
count++;
}
}
💻 Full Practical Example: Parallel Processing
Copy this to see how two threads run independently in the background:
public class MultiTasking {
public static void main(String[] args) {
Thread downloadThread = new Thread(() -> {
for (int i = 1; i <= 5; i++) {
System.out.println("Downloading: " + (i * 20) + "%");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
System.out.println("Download Complete!");
});
Thread musicThread = new Thread(() -> {
while (downloadThread.isAlive()) {
System.out.println("♪ Playing background music ♪");
try { Thread.sleep(1500); } catch (InterruptedException e) {}
}
});
downloadThread.start();
musicThread.start();
}
}
⚠️ Common Pitfall: start() vs run()
- If you call
t1.start(), Java creates a new thread. - If you call
t1.run(), Java runs the code on the current thread (no multitasking happens).
💡 Challenge: The Thread Race
- Create a
Runnabletask that prints its name and numbers 1 to 10. - Inside the loop, make the thread sleep for 500ms.
- In
main, create two threads with different names (e.g., "Thread-A" and "Thread-B"). - Start both and watch how their output overlaps in the terminal!