Multithreading
Modern applications rarely perform only one task at a time. They download data, process requests, update the UI, and log activity — all simultaneously.
Multithreading in Java allows a program to execute multiple tasks concurrently, improving performance and responsiveness.
What Is a Thread?
A thread is a lightweight unit of execution within a program.
A single Java program can have multiple threads running at the same time, each performing a different task.
For example:
- One thread handles user input
- Another thread processes data
- A third thread saves logs to disk
Why Multithreading Is Important
Without multithreading, a program executes tasks one after another, which can make applications slow and unresponsive.
Multithreading helps by:
- Improving application performance
- Utilizing CPU efficiently
- Keeping applications responsive
- Handling multiple users simultaneously
Creating a Thread Using Thread Class
One way to create a thread is by extending the Thread class.
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running");
}
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
The start() method begins execution of the thread.
Creating a Thread Using Runnable Interface
A more flexible and recommended approach is implementing Runnable.
class MyTask implements Runnable {
public void run() {
System.out.println("Runnable thread running");
}
public static void main(String[] args) {
Thread t = new Thread(new MyTask());
t.start();
}
}
This approach allows your class to extend another class if needed.
Thread Lifecycle
A thread goes through multiple states during its lifetime:
- New
- Runnable
- Running
- Blocked / Waiting
- Terminated
Understanding this helps in debugging and performance tuning.
Running Multiple Threads
Let us run two threads at the same time.
class Task extends Thread {
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
}
}
public static void main(String[] args) {
Task t1 = new Task();
Task t2 = new Task();
t1.start();
t2.start();
}
}
The output order may vary because threads run concurrently.
Real-World Example
Imagine an online shopping application:
- One thread processes payment
- Another thread updates inventory
- Another thread sends confirmation email
Multithreading makes such systems efficient and scalable.
Common Multithreading Problems
- Race conditions
- Data inconsistency
- Deadlocks
These problems occur when multiple threads access shared resources incorrectly.
Best Practices
- Use Runnable instead of Thread when possible
- Keep threads small and focused
- Avoid unnecessary shared data
- Use synchronization carefully
Key Takeaways
- Threads enable concurrent execution
- Improve performance and responsiveness
- Essential for backend and enterprise Java
In the next lesson, we will learn about Thread Synchronization and how to manage shared resources safely.