๐ Introduction
In todayโs world of high-performance applications, responsiveness and speed are crucial. Whether itโs a web server handling thousands of users or a desktop app performing background tasks, Multithreading plays a vital role. ๐ง โก
Java provides built-in support for multithreaded programming, allowing multiple parts of a program to execute simultaneously.
๐ In this detailed guide, we will deeply understand:
- What is Multithreading (concept + real understanding)
- Why and where it is used
- Thread Lifecycle (with detailed explanation of each state)
- Creating threads using Thread class and Runnable interface
- Important Thread class methods (with working programs)
- Thread Priority (how it works internally)
- Common mistakes & tricky concepts
- Interview questions with detailed answers
๐งต What is Multithreading?
Multithreading is the ability of a program to execute multiple threads concurrently.
๐ A thread is the smallest unit of execution within a process.
๐ง Key Concept:
- A process is a complete program (e.g., Chrome)
- A thread is a task inside that program (e.g., loading tab, playing video)
๐ฅ Why Use Multithreading?
โ 1. Better CPU Utilization
CPU doesnโt sit idle โ multiple threads keep it busy.
โ 2. Faster Execution
Tasks run in parallel (depending on CPU cores).
โ 3. Improved User Experience
UI does not freeze while performing background tasks.
โ 4. Real-world Applications
- Web servers ๐
- Gaming engines ๐ฎ
- Banking systems ๐ฆ
- File downloading ๐ฅ
๐ง Understanding with Example
Imagine downloading a file:
- Thread 1 โ Download file
- Thread 2 โ Show progress bar
- Thread 3 โ Accept cancel request
๐ All run simultaneously = Multithreading ๐ก
๐ Thread Life Cycle (Detailed Explanation)
A thread does not start running immediately after creation. It passes through multiple states.
๐งฉ Thread States:
๐น 1. NEW ๐
- Thread is created using
new Thread() - It has not started execution yet
Thread t = new Thread();
๐น 2. RUNNABLE โถ๏ธ
- After calling
start() - Thread is ready but waiting for CPU
๐น 3. RUNNING ๐
- Thread scheduler assigns CPU
- Thread executes
run()method
๐น 4. BLOCKED / WAITING โธ๏ธ
Thread enters this state when:
- Waiting for resource
- Waiting for another thread
- Using
sleep(),wait(),join()
๐น 5. TERMINATED โ
- Thread completes execution
- Cannot be restarted
๐ Lifecycle Flow
NEW โ RUNNABLE โ RUNNING โ WAITING/BLOCKED โ RUNNABLE โ TERMINATED
๐งฑ Creating Threads in Java
There are two main approaches:
๐น Method 1: Using Thread Class
โ Complete Program
class MyThread extends Thread {
@Override
public void run() {
// Code executed by thread
for(int i = 1; i <= 5; i++) {
System.out.println("Thread is running: " + i);
}
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
// Thread is in NEW state
t1.start(); // Moves to RUNNABLE
// Main thread execution
for(int i = 1; i <= 5; i++) {
System.out.println("Main thread: " + i);
}
}
}
๐ Overview of the Program
This program demonstrates:
- Creating a thread using Thread class
- Running two threads simultaneously:
- Main Thread ๐ง
- Child Thread ๐งต
๐ The goal is to show how Java executes multiple threads in parallel.
๐งฑ Step 1: Class Declaration
class MyThread extends Thread
๐ Explanation:
MyThreadis a custom class- It extends the Thread class, meaning:
- It becomes a thread itself
- It inherits thread behavior from Java
๐ By extending Thread, we can override its run() method.
โ๏ธ Step 2: Overriding run() Method
@Override
public void run() {
for(int i = 1; i <= 5; i++) {
System.out.println("Thread is running: " + i);
}
}
๐ Deep Explanation:
run()is the entry point of a thread- When a thread starts, this method is executed
๐ Loop Behavior:
- Runs from
i = 1toi = 5 - Prints:
Thread is running: 1 Thread is running: 2 ...
โ ๏ธ Important Concept:
๐ This code is executed by the child thread, NOT the main thread.
๐ง Step 3: main() Method Execution
public static void main(String[] args)
This is where the program starts execution.
๐งต Step 4: Creating Thread Object
MyThread t1 = new MyThread();
๐ What happens here?
- A thread object is created
- But thread has NOT started yet
๐ Thread State:
๐ NEW State ๐
๐ Step 5: Starting the Thread
t1.start();
๐ฅ What happens internally?
When start() is called:
- JVM creates a new thread
- Moves thread to RUNNABLE state
- Thread scheduler decides when to run it
- Internally calls
run()
โ ๏ธ Very Important:
๐ start() โ run()
| Method | Behavior |
|---|---|
start() | Creates new thread โ |
run() | Normal method call โ |
๐ง Step 6: Main Thread Execution
for(int i = 1; i <= 5; i++) {
System.out.println("Main thread: " + i);
}
๐ Explanation:
- This loop is executed by the main thread
- Runs independently of the child thread
โก Key Concept: Parallel Execution
At this point:
t1thread is runningrun()- Main thread is running its loop
๐ Both execute simultaneously
๐ Possible Output (NOT FIXED โ)
Main thread: 1
Thread is running: 1
Main thread: 2
Thread is running: 2
Thread is running: 3
Main thread: 3
Thread is running: 4
Main thread: 4
Thread is running: 5
Main thread: 5
๐คฏ Why output is mixed?
Because:
- CPU switches between threads
- This is called context switching
๐ Execution order is NOT predictable
๐ Thread Lifecycle in This Program
Step-by-step:
new MyThread()โ NEW ๐start()โ RUNNABLE โถ๏ธ- Scheduler picks thread โ RUNNING ๐
- Loop finishes โ TERMINATED โ
๐ง Internal Working (Very Important)
When start() is called:
- JVM does NOT immediately run
run() - It sends thread to scheduler
- Scheduler decides execution time
๐ This is why output is unpredictable
๐น Method 2: Using Runnable Interface (Best Practice โ )
โ Complete Program
class MyRunnable implements Runnable {
@Override
public void run() {
for(int i = 1; i <= 5; i++) {
System.out.println("Runnable thread: " + i);
}
}
public static void main(String[] args) {
MyRunnable obj = new MyRunnable();
Thread t1 = new Thread(obj); // Passing Runnable object
t1.start();
for(int i = 1; i <= 5; i++) {
System.out.println("Main thread: " + i);
}
}
}
๐ Why Runnable is Better?
- Java does not support multiple inheritance
- If you extend Thread, you cannot extend any other class โ
- Runnable allows flexibility โ
โ๏ธ Important Thread Class Methods (With Examples)
๐น 1. start() ๐
Starts a new thread.
Thread t = new Thread();
t.start();
๐น 2. sleep() ๐ด
Pauses thread execution.
โ Example
class SleepDemo {
public static void main(String[] args) throws InterruptedException {
for(int i = 1; i <= 5; i++) {
System.out.println(i);
Thread.sleep(1000); // 1 second delay
}
}
}
๐ Explanation:
- Thread pauses for given milliseconds
- Throws
InterruptedException
๐น 3. join() ๐ค
Waits for another thread to complete.
โ Example
class JoinDemo extends Thread {
public void run() {
for(int i = 1; i <= 5; i++) {
System.out.println("Child Thread: " + i);
}
}
public static void main(String[] args) throws InterruptedException {
JoinDemo t1 = new JoinDemo();
t1.start();
t1.join(); // Main thread waits
for(int i = 1; i <= 5; i++) {
System.out.println("Main Thread: " + i);
}
}
}
๐น 4. isAlive() ๐
Checks if thread is running.
System.out.println(t1.isAlive());
๐น 5. setName() / getName() ๐ท๏ธ
t1.setName("WorkerThread");
System.out.println(t1.getName());
๐น 6. currentThread() ๐ง
System.out.println(Thread.currentThread().getName());
๐ฏ Thread Priority (Deep Understanding)
Every thread has a priority that helps the scheduler decide execution order.
๐ Priority Levels:
| Constant | Value |
|---|---|
| MIN_PRIORITY | 1 |
| NORM_PRIORITY | 5 |
| MAX_PRIORITY | 10 |
โ Complete Example
class PriorityDemo extends Thread {
public void run() {
System.out.println(Thread.currentThread().getName() + " Priority: " + Thread.currentThread().getPriority());
}
public static void main(String[] args) {
PriorityDemo t1 = new PriorityDemo();
PriorityDemo t2 = new PriorityDemo();
t1.setName("Low Priority Thread");
t2.setName("High Priority Thread");
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}
๐ Important Notes:
- Higher priority โ More chance of execution (NOT guaranteed โ ๏ธ)
- Depends on OS scheduler
- Do NOT rely heavily on priority for logic
โ ๏ธ Common Mistakes (VERY IMPORTANT)
โ 1. Calling run() directly
No multithreading happens.
โ 2. Ignoring Exception Handling
Thread.sleep(1000); // must handle exception
โ 3. Assuming order of execution
Threads execute unpredictably โ
โ 4. Overusing threads
Too many threads โ performance issues
โ 5. Not understanding shared data issues
Leads to:
- Race conditions
- Data inconsistency
๐คฏ Common Confusions
๐ค start() vs run()
| Feature | start() | run() |
|---|---|---|
| Thread created | โ | โ |
| Async execution | โ | โ |
๐ค Is multithreading always faster?
๐ NO!
Depends on:
- CPU cores
- Task type
- Overhead
๐ผ Interview Questions (Detailed)
โ What is a thread?
๐ A lightweight unit of execution inside a process.
โ Difference between process and thread?
| Process | Thread |
|---|---|
| Heavyweight | Lightweight |
| Separate memory | Shared memory |
โ What is thread lifecycle?
๐ NEW โ RUNNABLE โ RUNNING โ WAITING โ TERMINATED
โ Why Runnable is preferred?
๐ Allows flexibility and avoids inheritance limitations.
โ What is join()?
๐ Makes one thread wait for another to finish.
โ What is sleep()?
๐ Pauses execution for a specified time.
๐ Conclusion
Multithreading is a core concept in Java that enables efficient, high-performance applications. ๐
In this detailed guide, you learned:
- โ๏ธ What multithreading is and why it matters
- โ๏ธ Thread lifecycle with complete understanding
- โ๏ธ Creating threads using Thread & Runnable
- โ๏ธ Important thread methods
- โ๏ธ Thread priority and behavior
- โ๏ธ Common mistakes & interview preparation
๐ฏ Final Advice
๐ Start practicing small programs
๐ Observe thread behavior carefully
๐ Move to advanced topics like:
- Synchronization
- Thread pools
- Executors framework
๐ป Happy Coding! ๐ฅ
Multithreading may seem tricky at first, but once you master it โ it becomes one of your strongest Java skills ๐ช