Java Concurrency Interview Questions — 20+ Essential Q&As (With Short, Clean Answers)

Java concurrency questions show up in almost every backend interview.
The goal of this guide is simple: give you short, clean explanations you can say out loud at a whiteboard — without drowning in theory.

This article assumes you’ve already read the basics from:
👉 Concurrency in Java — A Complete Beginner-Friendly Guide

Here, we focus only on interview-style questions and answers — practical, concise, and optimized for real backend interviews.

Use these as templates for your own explanations.

🟦 Section 1 — Core Concepts

Q1. What is concurrency in Java?

Short answer:
Concurrency means multiple tasks making progress at the same time.

Key points:

  • JVM achieves concurrency using multiple threads inside the same process.
  • Threads share memory → requires careful thread safety.
  • Concurrency improves responsiveness and scalability.

Q2. What is parallelism? How is it different from concurrency?

Short answer:

  • Concurrency → tasks appear to run together.
  • Parallelism → tasks literally run at the same time on multiple CPU cores.

Interview line:
“Concurrency is about structure; parallelism is about execution.”

Q3. What is a thread?

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

It has:

  • its own stack
  • its own program counter
  • shared heap memory with other threads

Q4. What is the difference between a process and a thread?

ProcessThread
Has its own memoryShares memory
Expensive to createLightweight
Heavy context switchingVery fast switching
Often multiple per OSMultiple inside JVM

Q5. What are the thread states in Java?

  • NEW
  • RUNNABLE
  • BLOCKED
  • WAITING
  • TIMED_WAITING
  • TERMINATED

Important:
➡ RUNNABLE includes both “ready to run” and “running”.
➜ A TERMINATED thread cannot be restarted or reused — calling start() again throws IllegalThreadStateException.

Q6. What is thread scheduling?

The OS scheduler decides which thread runs and for how long.

  • It is preemptive (threads can be interrupted).
  • It is not predictable — JVM gives no guarantees.

Q7. What is a critical section in Java? How is it different from a resource?

Short answer:
A resource is what multiple threads want to access.
A critical section is the code that accesses that resource and must be executed by only one thread at a time.

Detailed explanation
Developers often confuse these two concepts, but they are not the same. The resource is the shared data. The critical section is the protected code that uses the shared data.

Resource

A resource is the shared data that threads want to read or write.

Examples:

  • Shared variable (counter)
  • Shared object (List, Map)
  • File, socket, or DB connection
  • Any shared memory structure

Code example (resource only):

int counter;        // shared resource
List<String> list;  // shared resource

Critical Section

A critical section is the piece of code that operates on a shared resource and must not be executed by multiple threads at the same time.

Code example (critical section):

synchronized (lock) {       // critical section
    counter++;              // accessing shared resource
}

Comparison Table

(Add this using Gutenberg → Table block)

ConceptWhat It MeansExample
ResourceThe shared data that must be protectedShared variable, shared list
Critical SectionThe code that accesses/modifies the resourcesynchronized block incrementing a value

Perfect interview explanation

A resource is the shared data; a critical section is the protected code that accesses that data.

🟦 Section 2 — Thread Creation & Execution

Q8. How do you create a thread in Java?

Three primary ways:

  1. Implement Runnable
  2. Extend Thread
  3. Use ExecutorService (recommended)

Q9. Runnable vs Callable — what’s the difference?

FeatureRunnableCallable
Returns value?❌ No✅ Yes
Throws checked exceptions?❌ No✅ Yes
Works with thread pools?YesBest

Interview line:
“Callable is the modern choice when you need a result.”

Q10. What happens if you call run() instead of start()?

  • run() → behaves like a normal method → no new thread
  • start() → creates a new OS thread → runs run() inside it

Q11. Why should we avoid using new Thread()?

Because:

  • Threads are expensive
  • JVM cannot reuse them
  • Hard to manage a large number of threads
  • Risk of memory/CPU exhaustion

Use ExecutorService instead.

Q12. What is ExecutorService?

A framework for managing thread pools.

Benefits:

  • Reuses threads
  • Controls concurrency
  • Supports Callable & Future
  • Cleaner shutdown
  • Better performance under load

🟦 Section 3 — Synchronization & Thread Safety

Q13. What is a race condition?

When two or more threads access shared data and the final result depends on timing.

Q14. What is synchronization?

Synchronization ensures that only one thread executes a critical section at a time.

Tools include:

  • synchronized keyword
  • Locks
  • Atomic variables

Q15. Difference between sleep(), wait(), and yield()?

MethodPurpose
sleep()Pause without releasing lock
wait()Releases lock and waits for notify
yield()Suggests scheduler to switch threads

Q16. What is a deadlock?

A situation where two threads wait for each other’s locks and neither proceeds.

Interview tip:
➡ Two locks + two threads → instant deadlock example.

Q17. What is thread starvation?

A thread never gets CPU time because higher-priority threads dominate.

Q18. What is livelock?

Threads are active but make no progress because they continually react to each other.

🟦 Section 4 — Volatile, Locks, and Atomicity

Q19. What does volatile do?

volatile ensures:

  • Visibility: updates are seen immediately by other threads
  • Ordering: prevents instruction reordering

But:
➡ It does not make operations atomic.

Q20. What is atomicity?

An operation that is all-or-nothing, without interruption.

Example:
i++ is not atomic — needs a lock or atomic class.

Q21. What are atomic classes?

Examples include:

  • AtomicInteger
  • AtomicLong
  • AtomicBoolean

They provide lock-free, thread-safe operations.

Q22. Synchronized vs Lock — what’s the difference?

FeaturesynchronizedLock
Easy to use❌ More verbose
Auto unlock❌ Must unlock manually
Try lock?❌ NotryLock()
Interruptible waits?❌ No✔ Yes

Q23. What is ReadWriteLock?

Allows:

  • Multiple concurrent readers
  • Only one writer

Useful for read-heavy workloads.

🟦 Section 5 — java.util.concurrent Utilities

Q24. What is a Future?

A placeholder for an async result.

Limitations:

  • Cannot chain
  • Blocking get()
  • No composition

Q25. What is CompletableFuture?

A powerful async framework enabling:

  • Chaining
  • Combining tasks
  • Non-blocking pipelines
  • Timeouts & error handling

Q26. What are common thread pool types?

  • FixedThreadPool
  • CachedThreadPool
  • SingleThreadExecutor
  • ScheduledThreadPool
  • ForkJoinPool

Q27. What is a BlockingQueue?

A thread-safe queue that blocks automatically when full/empty.

Perfect for producer-consumer systems.

Q28. What are concurrent collections?

Examples:

  • ConcurrentHashMap
  • CopyOnWriteArrayList
  • ConcurrentLinkedQueue

Designed for multi-threaded environments.

🟦 Section 6 — High-Level and System Design Questions

Q29. How do you avoid deadlocks?

  • Acquire locks in a fixed order
  • Use tryLock() with timeouts
  • Reduce lock scope
  • Prefer immutable objects

Q30. How do you design a thread-safe class?

  • Make fields final
  • Use immutability
  • Use concurrent data structures
  • Minimize shared state

Q31. How do you improve concurrency performance?

  • Reduce lock contention
  • Use lock-free algorithms
  • Use appropriate thread pool sizes
  • Avoid blocking operations

Q32. When should you avoid concurrency?

  • When tasks are simple and sequential
  • When shared state is unavoidable and complex
  • When latency matters more than throughput

🟦 Section 7 — Real-World Scenarios: Choosing Runnable, Callable, or Thread


Q33. In a payment system, how do you choose between Runnable, Callable, and Thread?

Scenario
You’re designing a payment processing service that must:

  • Validate card details with Service A
  • Fetch a fraud score from Service B
  • Check account limits with Service C

All three calls are independent and may take 100–1000ms.
The system must respond in under 800ms.

What this implies
Running these calls sequentially is too slow.
We need parallel execution and we need return values from each call.

Correct choice: Callable + ExecutorService
Callable is ideal because:

  • Each task returns a value
  • Exceptions can be captured
  • ExecutorService manages thread reuse
  • Futures allow clean aggregation of results

Interview-ready answer
“A payment decision depends on multiple external calls. I’d call them in parallel using Callable tasks with an ExecutorService. Runnable is insufficient because I need return values, and raw Thread doesn’t scale.”


Q34. In a user signup workflow, when should you use Runnable instead of Callable?

Scenario
When a new user signs up, the system must:

  • Send a welcome email
  • Write an audit log entry

These operations are important but should not block the HTTP response.

What this implies
We need asynchronous execution, but no return values.
We simply need to “fire and forget.”

Correct choice: Runnable submitted to ExecutorService
Runnable is enough because:

  • No result needs to be returned
  • No exception propagation is needed
  • The main request should complete immediately

Interview-ready answer
“Signup should return quickly, so email and audit logging run asynchronously. Runnable is perfect because I don’t need return values. I’d submit these tasks to an ExecutorService rather than create raw Threads.”


Q35. For a CPU-heavy batch job, how do you choose between Runnable and Callable?

Scenario
A nightly batch job must process millions of records:

  • Workload is split into chunks
  • Each chunk performs CPU-heavy calculations
  • Some chunks may fail
  • The job must finish within one hour
  • The server has multiple CPU cores

What this implies
This is CPU-bound, and each chunk can run in parallel.
The concurrency level should match the number of cores.
Each chunk may or may not need to return a result.

Correct choice: Runnable or Callable depending on return values

Use Callable when:

  • Each batch returns metrics (processed count, error count)

Use Runnable when:

  • The batch writes output directly and does not need to return data

In both cases:
Use ExecutorService with a fixed thread pool sized to available cores.

Interview-ready answer
“For CPU-heavy workloads, I’d divide the data into chunks and run them in parallel using a fixed thread pool sized to the machine’s cores. If each chunk needs to return a summary, I’d use Callable. If not, Runnable is enough. Raw Threads are unnecessary and don’t scale.”

🟦 Conclusion

Java concurrency appears in every backend engineering interview.

Use these Q&As as templates for explaining concepts in a clear, confident, senior-level tone.

If you haven’t read the foundational tutorial yet, start here:
👉 Concurrency in Java — A Complete Beginner-Friendly Guide

Did this tutorial help you?

If you found this useful, consider bookmarking Code & Candles or sharing it with a friend.

Explore more tutorials

Leave a Comment

Your email address will not be published. Required fields are marked *