Short Answer:
Threading in Java allows multiple tasks to run concurrently within a single program.
A thread is a lightweight subprocess. Java supports multithreading to improve performance and resource utilization.
1️⃣ Thread Life Cycle
NEW → RUNNABLE → RUNNING → BLOCKED/WAITING → TERMINATED
- NEW: Thread created
- RUNNABLE: Ready to run
- RUNNING: Executing
- BLOCKED/WAITING: Waiting for resource
- TERMINATED: Finished execution
2️⃣ Ways to Create Thread
Method 1: Extending Thread Class
class MyThread extends Thread {
public void run() {
System.out.println("Thread Running");
}
}
MyThread t = new MyThread();
t.start();
Method 2: Implementing Runnable (Recommended)
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread Running");
}
}
Thread t = new Thread(new MyRunnable());
t.start();
3️⃣ Important Thread Methods
- start()
- run()
- sleep()
- join()
- yield()
- interrupt()
4️⃣ Synchronization
Short: Used to avoid race condition.
synchronized void display() {
System.out.println("Synchronized Method");
}
- Ensures only one thread accesses critical section.
- Uses intrinsic lock (monitor).
5️⃣ Important Multithreading Concepts
- Race Condition
- Deadlock
- Starvation
- Thread Pool
- Executor Framework
Executor Framework Example
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> System.out.println("Task"));
executor.shutdown();
Frequently Asked Interview Questions
1️⃣ Difference between Thread and Runnable?
Short: Runnable is preferred because it supports multiple inheritance and better design.
Thread class defines both task and execution mechanism. Runnable separates task (logic) from execution (Thread).
class Task implements Runnable {
public void run() {
System.out.println("Running Task");
}
}
Thread t = new Thread(new Task());
t.start();
Interview Tip: Always prefer Runnable in real projects.
2️⃣ Difference between start() and run()?
Short: start() creates new thread; run() executes like normal method.
Thread t = new Thread(() -> {
System.out.println("Thread Running");
});
t.run(); // No new thread created
t.start(); // New thread created
Calling run() directly does NOT create a new thread.
3️⃣ What is Synchronization?
Short: Prevents race condition.
When multiple threads access shared resource simultaneously, inconsistent results may occur.
class Counter {
int count = 0;
synchronized void increment() {
count++;
}
}
Without synchronization → wrong count value possible.
4️⃣ What is Deadlock?
Short: Two threads waiting for each other's lock.
Thread 1 locks A and waits for B Thread 2 locks B and waits for A
Deadlock prevention:
- Lock ordering
- Timeout locks
- Avoid nested locks
5️⃣ What is Thread Pool?
Short: Reuses threads instead of creating new ones.
ExecutorService service = Executors.newFixedThreadPool(2);
service.submit(() -> {
System.out.println("Task Executed");
});
service.shutdown();
Benefits:
- Better performance
- Controlled thread creation
- Used in production systems
6️⃣ What is volatile keyword?
Short: Ensures visibility across threads.
Without volatile, one thread may not see updated value from another thread.
class Test {
volatile boolean flag = true;
}
volatile ensures visibility but NOT atomicity.
7️⃣ Difference between sleep() and wait()?
| sleep() | wait() |
| Thread class method | Object class method |
| Does not release lock | Releases lock |
| Used for delay | Used for inter-thread communication |
8️⃣ What is Callable?
Short: Runnable that returns result.
Callabletask = () -> 10; ExecutorService service = Executors.newSingleThreadExecutor(); Future result = service.submit(task); System.out.println(result.get());
9️⃣ What is Future?
Short: Represents result of async task.
- get() → get result
- cancel() → cancel task
- isDone() → check completion
🔟 What is CAS?
Short: Compare-And-Swap for lock-free programming.
Used internally in Atomic classes.
AtomicInteger count = new AtomicInteger(0); count.incrementAndGet();
Advanced Multithreading in Java – Complete Guide
Short Summary:
Java Multithreading works based on Java Memory Model (JMM), synchronization mechanisms, Executor framework, and asynchronous programming using CompletableFuture.
1️⃣ Java Memory Model (JMM) Explained
Short: JMM defines how threads interact through memory.
Each thread has:
- Stack Memory → Local variables
- Heap Memory → Shared objects
Threads work with their own local cache copy of variables.
Key JMM Concepts
- Visibility → Changes by one thread visible to others.
- Atomicity → Operation happens completely or not at all.
- Happens-Before Relationship
Example (Visibility Issue)
class Test {
static boolean flag = false;
public static void main(String[] args) {
new Thread(() -> {
while(!flag) {}
System.out.println("Stopped");
}).start();
flag = true; // May not be visible without volatile
}
}
Use volatile to fix visibility.
2️⃣ Deadlock – Real Runnable Example
Short: Two threads waiting for each other's lock.
class DeadlockExample {
static final Object lock1 = new Object();
static final Object lock2 = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized(lock1) {
try { Thread.sleep(100); } catch(Exception e) {}
synchronized(lock2) {
System.out.println("Thread 1");
}
}
});
Thread t2 = new Thread(() -> {
synchronized(lock2) {
synchronized(lock1) {
System.out.println("Thread 2");
}
}
});
t1.start();
t2.start();
}
}
Prevention:
- Lock ordering
- Using tryLock()
- Avoid nested locks
3️⃣ ExecutorService – Complete Deep Dive
Short: Manages thread pool efficiently.
Types of Thread Pools
- newFixedThreadPool()
- newCachedThreadPool()
- newSingleThreadExecutor()
- newScheduledThreadPool()
Example
ExecutorService service = Executors.newFixedThreadPool(2);
service.submit(() -> {
System.out.println("Task Running");
});
service.shutdown();
Executor Lifecycle
- submit()
- shutdown()
- shutdownNow()
- awaitTermination()
Best practice: Always shutdown executor.
4️⃣ CompletableFuture Explained Clearly
Short: Used for asynchronous non-blocking programming.
Basic Example
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(result -> result + " Java")
.thenAccept(System.out::println);
Combining Futures
CompletableFuturef1 = CompletableFuture.supplyAsync(() -> "A"); CompletableFuture f2 = CompletableFuture.supplyAsync(() -> "B"); f1.thenCombine(f2, (a, b) -> a + b) .thenAccept(System.out::println);
Advantages:
- Non-blocking
- Better than Future
- Chainable
Advanced Multithreading Scenario Questions
1️⃣ What is Java Memory Model?
Answer: Defines visibility, atomicity, and ordering rules between threads.
2️⃣ How does volatile differ from synchronized?
Answer: volatile ensures visibility only; synchronized ensures visibility + atomicity.
3️⃣ How to avoid deadlock?
Answer: Maintain consistent lock order and use tryLock().
4️⃣ Difference between Callable and Runnable?
Answer: Callable returns result and throws checked exception.
5️⃣ What is ForkJoinPool?
Answer: Used for parallel tasks using divide-and-conquer.
6️⃣ What is happens-before principle?
Answer: Ensures memory visibility order between threads.
7️⃣ What causes thread starvation?
Answer: When low-priority threads never get CPU time.
0 comments