13. Java Multithreading
T
Tuan Nguyen

13. Java Multithreading

This section focuses on Java concurrency and multithreading concepts, including threads, synchronization, thread safety, race conditions, locks, concurrent collections, thread pools, and modern concurrency features such as virtual threads in Java 21.

1. What is thread?

A thread is the smallest unit of execution inside a process.

A Java application can run multiple threads simultaneously.

Example:

Main thread
Worker thread
Background thread

Each thread has:

Its own stack memory
Execution flow
Program counter

Threads inside the same process share:

Heap memory
Objects
Resources

Threads allow concurrent task execution.


2. Difference between process and thread?


Process

A process is an independent running application.

Each process has its own:

Memory space
Resources
Execution environment

Example:

Chrome browser
Spotify
IDE

Thread

A thread is a lightweight execution unit inside a process.

Threads share process memory.


Main differences:

Process

Thread

Heavyweight

Lightweight

Separate memory

Shared memory

Expensive creation

Faster creation

More isolated

More communication risk


3. What is multithreading?

Multithreading means running multiple threads concurrently within one application.

Example:

One thread handles API requests
One thread processes payments
One thread sends emails

Benefits:

Better responsiveness
Parallel processing
Higher throughput
Resource efficiency

Multithreading is heavily used in backend systems.


4. Why is multithreading important?

Modern backend systems handle many concurrent operations:

HTTP requests
Database calls
Kafka consumers
Background jobs
External API calls

Without multithreading, applications would process tasks sequentially and become very slow.

Multithreading improves:

Scalability
CPU utilization
Concurrency
Performance

5. How do you create thread?

Two common approaches.


Extend Thread

Example:

class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println("Running");
    }
}

Implement Runnable

Example:

class MyTask implements Runnable {

    @Override
    public void run() {
        System.out.println("Running");
    }
}

Then:

new Thread(new MyTask()).start();

Implementing Runnable is preferred because Java supports only single inheritance.


6. Difference between Runnable and Callable?

Runnable

Callable

No return value

Returns value

run() method

call() method

Cannot throw checked exceptions

Can throw checked exceptions

Example Runnable:

Runnable task = () -> {
    System.out.println("Hello");
};

Example Callable:

Callable<Integer> task = () -> 10;

Callable is more flexible for async computations.


7. What is Future?

Future represents the result of an asynchronous operation.

Example:

Future<Integer> future =
    executor.submit(() -> 10);

Later:

future.get();

retrieves the result.

Future allows:

Async processing
Result retrieval
Task cancellation
Status checking

8. What is CompletableFuture?

CompletableFuture is an advanced asynchronous programming API introduced in Java 8.

Example:

CompletableFuture.supplyAsync(() -> "Hello")
    .thenApply(String::toUpperCase)
    .thenAccept(System.out::println);

Advantages over Future:

Chaining
Non-blocking callbacks
Combining async tasks
Better async composition

Very common in modern backend applications.


9. What is thread pool?

A thread pool is a collection of reusable threads.

Instead of creating new threads repeatedly:

Reuse existing threads

Benefits:

Better performance
Lower overhead
Controlled concurrency
Reduced resource usage

Thread pools are essential in enterprise systems.


10. What is ExecutorService?

ExecutorService is a framework for managing thread execution.

Example:

ExecutorService executor =
    Executors.newFixedThreadPool(10);

Instead of manually creating threads:

new Thread(...)

ExecutorService manages threads internally.

Benefits:

Thread pooling
Task scheduling
Lifecycle management
Better scalability

11. What is race condition?

Race condition occurs when multiple threads access shared mutable data simultaneously and execution order affects results.

Example:

counter++;

Two threads incrementing at same time may produce incorrect value.

Race conditions cause:

Data corruption
Inconsistent state
Unpredictable bugs

12. What is synchronization?

Synchronization controls concurrent access to shared resources.

Goal:

Only one thread accesses critical section at a time

Synchronization prevents race conditions.


13. What is synchronized keyword?

synchronized provides thread-safe access using locks.

Example:

public synchronized void increment() {
    counter++;
}

Only one thread can execute the synchronized block or method at a time for the same object.


14. What is monitor lock?

Every Java object has an internal monitor lock.

synchronized uses this monitor internally.

Example:

synchronized(this) {
}

A thread must acquire the object's monitor lock before entering the synchronized block.


15. What is intrinsic lock?

Intrinsic lock is the built-in lock associated with every Java object.

It is the same lock used by:

synchronized

Intrinsic locks are also called monitor locks.


16. What is deadlock?

Deadlock happens when threads wait for each other indefinitely.

Example:

Thread A holds Lock 1 and waits for Lock 2
Thread B holds Lock 2 and waits for Lock 1

Neither thread can continue.

Deadlocks can freeze applications.


17. How do you prevent deadlock?

Common strategies:

Strategy

Explanation

Consistent lock ordering

Always acquire locks in same order

Timeout locks

Avoid infinite waiting

Reduce nested locking

Simpler locking design

Use concurrent utilities

Higher-level abstractions

Consistent lock ordering is one of the most important deadlock prevention techniques.


18. What is livelock?

Livelock happens when threads are active but continuously reacting to each other without making progress.

Example:

Thread A backs off for Thread B
Thread B backs off for Thread A
Both repeat forever

Unlike deadlock, threads are not blocked, but useful work never completes.


19. What is starvation?

Starvation occurs when a thread never gets enough CPU time or resources to execute.

Example:

High-priority threads always execute
Low-priority thread never runs

Starvation can happen with unfair locking or scheduling.


20. What is volatile?

volatile guarantees visibility of variable updates between threads.

Example:

private volatile boolean running = true;

If one thread changes:

running = false;

other threads immediately see updated value.

Without volatile, threads may cache old values.


21. Difference between volatile and synchronized?


volatile

Provides:

Visibility only

No locking.

No atomicity.


synchronized

Provides:

Visibility
Atomicity
Mutual exclusion

Prevents multiple threads entering critical section simultaneously.


Main difference:

volatile

synchronized

Lightweight

Heavier

No locking

Uses locks

Visibility only

Full synchronization


22. What is atomic operation?

Atomic operation executes completely or not at all.

Example:

No intermediate state visible

Simple read/write operations may be atomic, but:

counter++;

is NOT atomic.

It involves:

Read
Modify
Write

Multiple threads can interfere.


23. What is AtomicInteger?

AtomicInteger provides thread-safe atomic operations without synchronized blocks.

Example:

AtomicInteger counter = new AtomicInteger(0);

counter.incrementAndGet();

Internally uses low-level CPU operations for better concurrency performance.

Useful for counters and shared numeric state.


24. What is ConcurrentHashMap?

ConcurrentHashMap is a thread-safe version of HashMap.

Example:

ConcurrentHashMap<String, Integer> map =
    new ConcurrentHashMap<>();

Advantages:

Concurrent reads/writes
Better scalability
Thread safety

Unlike Hashtable, ConcurrentHashMap uses finer-grained locking for better performance.


25. What is thread-safe?

Thread-safe means code behaves correctly when accessed by multiple threads concurrently.

Thread-safe classes prevent:

Race conditions
Data corruption
Inconsistent state

Examples:

ConcurrentHashMap
AtomicInteger
CopyOnWriteArrayList

26. What collections are thread-safe?

Examples:

Collection

Thread-safe

Vector

Yes

Hashtable

Yes

ConcurrentHashMap

Yes

CopyOnWriteArrayList

Yes

Normal collections like:

ArrayList
HashMap
HashSet

are NOT thread-safe.


27. What is CopyOnWriteArrayList?

CopyOnWriteArrayList creates a new copy of the array whenever modification occurs.

Advantages:

Thread-safe iteration
No ConcurrentModificationException

Disadvantages:

Expensive writes
High memory usage

Best for:

Read-heavy workloads
Rare modifications

28. What is blocking queue?

BlockingQueue is a thread-safe queue used for producer-consumer patterns.

Example:

BlockingQueue<String> queue =
    new LinkedBlockingQueue<>();

Features:

Thread-safe
Blocks when empty/full
Useful for worker systems

Commonly used in:

Thread pools
Message processing
Background workers

29. What are virtual threads?

Virtual threads are lightweight threads introduced by Project Loom.

Example:

Thread.startVirtualThread(() -> {
    System.out.println("Hello");
});

Unlike platform threads, virtual threads are managed mainly by the JVM instead of directly by the operating system.

Advantages:

Much lower memory usage
Massive concurrency
Simpler async programming

30. Why are virtual threads important in Java 21?

Traditional platform threads are expensive.

Large backend systems may require:

Thousands
or millions
of concurrent requests

Platform threads consume significant OS resources.

Virtual threads solve this problem by allowing massive concurrency with lightweight scheduling.

Benefits:

High scalability
Simpler concurrent code
Reduced thread overhead
Better IO-heavy performance

Virtual threads are especially important for:

Microservices
REST APIs
Database-heavy systems
Network servers

Java 21 made virtual threads production-ready, making them one of the biggest modern Java concurrency improvements.

Comments