What is Multithreading in Java?
Multithreading in Java allows concurrent execution of two or more threads within a single program. Each thread performs a specific task, helping achieve parallel execution for better performance and resource utilization. Threads in Java are lightweight sub-processes that share the same memory space.
class Task1 extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Task 1 - Count: " + i);
try { Thread.sleep(100); } catch (InterruptedException e) {}
}
}
}
class Task2 extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Task 2 - Count: " + i);
try { Thread.sleep(100); } catch (InterruptedException e) {}
}
}
}
public class MultiThreadExample {
public static void main(String[] args) {
Task1 t1 = new Task1();
Task2 t2 = new Task2();
t1.start();
t2.start();
System.out.println("Both threads running concurrently...");
}
}
Output: Both threads run concurrently, displaying interleaved results (Task 1 and Task 2 counts mixed together).
What is Multitasking in Java?
Multitasking means the ability of an operating system to execute multiple programs or processes simultaneously. Java supports multitasking using two approaches:
- Process-based Multitasking: Multiple programs running simultaneously (e.g., browser + music player + IDE)
- Thread-based Multitasking: Multiple threads within a single program running concurrently
Running a Java program while listening to music and downloading a file — all at the same time. Each task runs independently in separate processes handled by the OS.
Multithreading vs Multitasking
| Aspect | Multithreading | Multitasking |
|---|---|---|
| Definition | Executing multiple threads within a single program | Executing multiple programs/processes simultaneously |
| Granularity | Thread level (lightweight) | Process level (heavier) |
| Memory Sharing | Threads share same memory space | Processes have separate memory spaces |
| Communication | Easy via shared memory | Complex via IPC (Inter-Process Communication) |
| Context Switching 那些人Faster (within same process) | Slower (between different processes) | |
| Example | A web browser using multiple threads for tabs | Running Word, Chrome, and Calculator together |
Objectives of Multithreading & Multitasking
🔹 Improve program performance by executing tasks concurrently
🔹 Utilize system resources (CPU, memory) efficiently
🔹 Enable simultaneous operations for smoother user experience
🔹 Reduce idle time of CPU by running multiple tasks
🔹 Enhance application responsiveness in UI applications
Advantages of Multithreading & Multitasking
🚀 Faster execution and responsiveness: Multiple tasks run in parallel, reducing overall execution time
💻 Better CPU utilization: Keeps CPU busy by switching between tasks when one is waiting
📊 Efficient use of idle processor time: Utilizes idle CPU cycles for background tasks
🎮 Supports real-time, parallel operations: Ideal for gaming, multimedia, and server applications
🔧 Improved resource sharing: Threads share memory and resources efficiently
Limitations of Multithreading & Multitasking
🔒 Thread synchronization complexity: Requires careful management to avoid race conditions
🐞 Debugging multithreaded code is harder: Issues like deadlocks and race conditions are difficult to reproduce
💀 Improper handling may lead to deadlocks: Threads waiting indefinitely for resources
📈 Performance overhead if too many threads are created: Excessive context switching overhead
💾 Increased memory consumption: Each thread requires its own stack memory
Thread Life Cycle States
A thread in Java goes through these 5 states during its lifetime.
Multithreading Implementation Process
- Create threads using
Threadclass (extends) orRunnableinterface (implements) - Start threads using
start()method (callsrun()internally) - Manage execution using
sleep(),join(), andsynchronizedkeywords - Monitor thread lifecycle and handle exceptions (
InterruptedException) - Terminate threads naturally after task completion or using interruption
Two Ways to Create Threads in Java
class MyThread extends Thread {
public void run() {
System.out.println("Thread running");
}
}
MyThread t = new MyThread();
t.start();
2. Implementing Runnable Interface:
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable thread running");
}
}
Thread t = new Thread(new MyRunnable());
t.start();
Note: Implementing Runnable is preferred because Java supports single inheritance only.
Best Practices for Multithreading & Multitasking
Use proper synchronization mechanisms to prevent race conditions
Keep thread tasks lightweight and independent when possible
Utilize thread pools (ExecutorService) for managing large numbers of threads
Handle exceptions properly inside threads to maintain stability
Avoid using Thread.stop() (deprecated) — use flags or interruption instead
Use concurrent collections (ConcurrentHashMap) instead of manual synchronization
Prefer Runnable over Thread for better flexibility and reusability
Use volatile keyword for variables accessed by multiple threads