Multithreading in Java

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.

Callable task = () -> 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

CompletableFuture f1 = 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

Leave a comment