40 Essential Java Multithreading Interview Questions Explained

This article compiles and clarifies forty common Java multithreading interview questions, covering thread creation, synchronization mechanisms, thread pools, memory model, and practical debugging techniques to help developers deepen their understanding and prepare for technical interviews.

ITPUB
ITPUB
ITPUB
40 Essential Java Multithreading Interview Questions Explained

1. What is the purpose of multithreading?

Multithreading leverages multi‑core CPUs to run multiple logical tasks concurrently, prevents blocking when a thread waits for I/O, and simplifies modeling by decomposing a large task into smaller, independently runnable subtasks.

2. Ways to create a thread

Two common approaches: (1) extend the Thread class, (2) implement the Runnable interface. Implementing Runnable is preferred because it reduces coupling and follows interface‑driven design.

3. Difference between start() and run()

Calling start() creates a new thread and executes run() concurrently. Directly invoking run() runs the code synchronously in the current thread.

4. Runnable vs Callable

Runnable

's run() returns void. Callable 's call() returns a value and works with Future / FutureTask to retrieve results or cancel execution.

5. Difference between CyclicBarrier and CountDownLatch

CyclicBarrier

makes all participating threads wait until each reaches the barrier, then releases them together; it can be reused. CountDownLatch only counts down; threads continue after the count reaches zero and it cannot be reused. CyclicBarrier can wake a single task, while CountDownLatch can release multiple waiting tasks.

6. Role of the volatile keyword

volatile

guarantees visibility of variable updates across threads and prevents certain reordering optimizations, though it may slightly reduce performance. It is often combined with CAS to achieve atomicity.

7. What is thread safety?

A piece of code is thread‑safe if it produces the same result when executed concurrently as when executed sequentially. Levels include immutable objects, absolutely thread‑safe classes (e.g., CopyOnWriteArrayList), relatively thread‑safe classes (e.g., Vector), and non‑thread‑safe classes (e.g., ArrayList).

8. How to obtain a thread dump in Java

Use jps to get the PID, then jstack PID or kill -3 PID to print stack traces. The Thread.getStackTrace() method can also retrieve a thread's stack.

9. What happens if a thread throws an uncaught runtime exception?

The thread terminates and releases any monitors it holds.

10. Sharing data between threads

Share objects and coordinate via wait/notify (or await/signal) mechanisms; concurrent collections like BlockingQueue are designed for this purpose.

11. Difference between sleep() and wait()

sleep()

pauses the current thread without releasing its monitor; wait() releases the monitor and waits to be notified.

12. Purpose of the producer‑consumer model

Balances production and consumption rates to improve overall throughput.

Decouples producers from consumers, allowing independent evolution.

13. Use of ThreadLocal

Provides thread‑confined storage, eliminating the need for synchronization on that data.

14. Why must wait() and notify() be called inside a synchronized block?

Both methods require the calling thread to hold the object's monitor, which is ensured by entering a synchronized block.

15. Difference in monitor release between wait() and notify()

wait()

releases the monitor immediately; notify() releases it only after the synchronized block completes.

16. Why use a thread pool?

To reuse thread objects, reduce creation overhead, and control the level of concurrency.

17. Detecting if a thread holds a monitor

Use Thread.holdsLock(Object), which returns true only if the current thread holds the monitor of the given object.

18. synchronized vs ReentrantLock

ReentrantLock

offers configurable lock acquisition timeouts, richer introspection, and multiple condition variables.

Implementation differs: ReentrantLock uses Unsafe.park, while synchronized manipulates the object header.

19. Concurrency level of ConcurrentHashMap

Defined by the number of segments (default 16), allowing up to 16 threads to modify the map simultaneously.

20. What is ReadWriteLock ?

Provides separate read and write locks; multiple threads can hold the read lock concurrently, while the write lock is exclusive, improving performance for read‑heavy workloads.

21. What is FutureTask ?

An implementation of both Runnable and Future that wraps a Callable, allowing asynchronous execution and result retrieval, and can be submitted to a thread pool.

22. Finding the CPU‑intensive thread on Linux

Obtain the Java process PID via jps or ps -ef | grep java.

Run top -H -p PID to list thread CPU usage (LWP IDs).

Map LWP IDs (decimal) to Java thread IDs (hex) to locate the hot thread's stack.

23. Example code that causes a deadlock

Two threads each lock two objects in opposite order (lock1 then lock2 vs lock2 then lock1), causing a circular wait.

24. How to wake a blocked thread

Interrupt the thread (throws InterruptedException) if it is waiting on wait(), sleep(), or join(). I/O‑blocked threads cannot be directly awakened from Java.

25. Benefits of immutable objects in multithreading

Immutable objects guarantee visibility without additional synchronization, improving performance.

26. What is a context switch?

The CPU switches execution from one running thread to another ready thread.

27. What happens when a thread‑pool queue is full?

With an unbounded LinkedBlockingQueue, tasks are simply queued.

With a bounded queue (e.g., ArrayBlockingQueue), the RejectedExecutionHandler handles overflow, defaulting to AbortPolicy.

28. Thread scheduling algorithm in Java

Preemptive scheduling based on thread priority, starvation, and other factors.

29. Effect of Thread.sleep(0)

Hints to the scheduler to yield the current time slice, helping lower‑priority threads obtain CPU time.

30. What is spinning?

Instead of blocking, a thread repeatedly checks a lock (busy‑wait) for a short period before deciding to block, reducing kernel‑mode transitions for short critical sections.

31. Java Memory Model (JMM)

Defines main memory vs. working memory, atomic operations, volatile rules, and the happens‑before relationship that determines visibility and ordering guarantees.

32. What is CAS?

Compare‑And‑Swap atomically updates a memory location if its current value matches an expected value, typically used with volatile variables.

33. Optimistic vs. pessimistic locking

Optimistic lock assumes conflicts are rare and uses CAS with retry logic.

Pessimistic lock assumes conflicts are common and acquires an exclusive lock (e.g., synchronized).

34. What is AQS?

AbstractQueuedSynchronizer is the core framework for Java's concurrency utilities (e.g., ReentrantLock, CountDownLatch, Semaphore), managing a FIFO wait queue and providing tryLock / tryRelease hooks for subclasses.

35. Thread safety of singleton patterns

Eager initialization – thread‑safe.

Lazy initialization – not thread‑safe without synchronization.

Double‑checked locking – thread‑safe when implemented correctly.

36. Role of Semaphore

Limits concurrent access to a resource by a fixed number of permits; a permit count of 1 behaves like a mutex.

37. Why synchronize Hashtable.size() ?

Even a single‑statement method can suffer from race conditions because underlying bytecode may translate to multiple machine instructions, and without synchronization the returned count may be stale.

38. Who invokes a thread class's constructor and static block?

The thread that creates the instance (e.g., new Thread()) runs the constructor and static initializer; the thread's run() method is executed by the new thread itself.

39. Synchronized method vs. synchronized block

Synchronized blocks reduce the locked region, improving performance. However, the JVM may perform lock‑coarsening for frequently called small synchronized methods (e.g., StringBuffer.append).

40. Thread‑pool sizing strategies

High concurrency, short tasks: set pool size to CPU cores + 1.

Low concurrency, long‑running I/O‑bound tasks: increase pool size to keep CPUs busy.

Low concurrency, long‑running CPU‑bound tasks: keep pool size modest to reduce context switches.

High concurrency, long‑running tasks: consider architectural changes, caching, or middleware rather than just tuning the pool.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Synchronizationmultithreadinginterviewthread poolJava Memory Model
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.