$ Java Multithreading & Exception Handling — Complete Interview Revision
// 6-7 Yrs Experience — Spring Boot & Microservices Focus
Part I
Java Multithreading
1. Fundamentals & Thread Lifecycle
Quick Reference
Basics
Process, Thread, Lifecycle, Creation
Safety
Race Condition, Sync, Volatile, Atomic, Locks
Coordination
wait/notify, Latch, Barrier, Semaphore
Modern Java
Executor, CompletableFuture, ForkJoin, Concurrent Collections
Legend
Core Concept
Sync / Safety
Executor / Async
Collections / Utilities
Danger Zone (Deadlock/Starvation)
Core Definitions (Say These First)
ProcessAn independently running application with its own memory space
ThreadSmallest unit of execution, runs inside a process, shares its memory
MultithreadingMultiple threads run concurrently within one process, sharing memory
ConcurrencyMultiple tasks make progress in overlapping time (not necessarily the same instant)
ParallelismMultiple tasks run truly simultaneously on multiple CPU cores
Thread Lifecycle
State Transitions
NEW
→ start() →
RUNNABLE
RUNNING
RUNNING
BLOCKED / WAITING / TIMED_WAITING
TERMINATED
StateMeaning
NEWThread object created, start() not yet called
RUNNABLEEligible to run — moves here after start()
RUNNINGCPU is actively executing this thread
BLOCKEDWaiting to acquire a monitor lock held by another thread
WAITINGWaiting indefinitely — wait(), join() without timeout
TIMED_WAITINGWaiting a fixed time — sleep(), wait(ms), join(ms)
TERMINATEDRun completed (normally or via exception)
2. Thread Creation
Thread Creation Options
OptionNotes
extends ThreadSimplest, but no multiple inheritance — avoid in practice
implements RunnablePreferred — no return value, no checked exceptions
Callable<V>Returns a value, can throw checked exceptions
Future<V>Handle to result of async task — get() blocks
CompletableFutureNon-blocking, chainable, combinable async pipeline
Runnable
ReturnNo return value
ExceptionsNo checked exceptions
Methodrun()
Callable
ReturnReturns a value (V)
ExceptionsCan throw checked exceptions
Methodcall()
3. Thread Safety — Race Condition, Sync, Visibility, Atomicity
Race Condition & Synchronization
Race Condition≥2 threads read-modify-write same shared state concurrently → lost updates
Critical SectionCode block touching shared state; must run exclusively
synchronized methodLocks this (instance monitor) for the whole method
synchronized blocksynchronized(obj){...} — locks only the critical section
static synchronizedLocks the Class object — one lock across all instances
Monitor / Intrinsic LockBuilt-in lock every Java object has; backbone of synchronized
Visibility & Atomicity
volatileGuarantees visibility of latest value across threads — NOT atomicity
AtomicInteger / AtomicLongLock-free, thread-safe counters via incrementAndGet() etc.
AtomicReferenceAtomic updates to object references
CASCompare-And-Swap: read → compare expected → update or retry (lock-free)
Common Comparisons
volatile
GuaranteesVisibility only
CASNo CAS
count++Unsafe
AtomicInteger
GuaranteesVisibility + Atomicity
CASUses CAS internally
count++Safe
4. Locking Mechanisms & Deadlock Management
Locking Mechanisms
ReentrantLockExplicit lock — tryLock(), fairness, interruptibility
ReadWriteLockMultiple readers OR one writer — great for read-heavy caches
StampedLockAdds optimistic read mode — faster than ReadWriteLock
Fair Locknew ReentrantLock(true) — grants lock in request order
tryLock()Attempts lock, returns immediately/with timeout instead of blocking
Deadlock, Starvation, Livelock
DeadlockThreads hold-and-wait on each other's locks in a cycle → all stuck forever
StarvationA thread never gets CPU/lock because others keep getting priority
LivelockThreads keep responding to each other but make no real progress
PreventionConsistent lock ordering, tryLock()+timeout, avoid nested locks
Classic Deadlock Example
// Thread-1 lock(A); lock(B); // Thread-2 (reverse order = deadlock) lock(B); lock(A);
ReentrantLock with tryLock
Lock lock = new ReentrantLock(); if (lock.tryLock(5, TimeUnit.SECONDS)) { try { /* work */ } finally { lock.unlock(); } }
5. Thread Communication — wait() / notify() / notifyAll() / sleep()
MethodBehavior
wait()Releases the lock and waits until notified — must be inside a synchronized block (Object class)
notify()Wakes ONE waiting thread (unspecified which)
notifyAll()Wakes ALL waiting threads
sleep()Pauses the thread but KEEPS the lock (Thread class, not Object)
wait() / notifyAll()
synchronized(lock) { while (!ready) lock.wait(); // proceed after notifyAll() }
wait() vs sleep()
// wait(): releases lock, Object class, needs synchronized // sleep(): keeps lock, Thread class, no synchronized needed
6. Executor Framework & Thread Pools
Executor Framework
ExecutorBase interface — just execute(Runnable)
ExecutorServiceAdds submit(), shutdown(), returns Future
ScheduledExecutorServiceRun tasks after a delay / periodically
FixedThreadPoolFixed N threads, unbounded queue
CachedThreadPoolGrows/shrinks dynamically — risky under heavy load
SingleThreadExecutorOne thread, tasks run sequentially in order
ScheduledThreadPoolFixed pool for scheduled/repeating jobs
Production: ThreadPoolTaskExecutor
@Bean Executor taskExecutor() { ThreadPoolTaskExecutor ex = new ThreadPoolTaskExecutor(); ex.setCorePoolSize(10); ex.setMaxPoolSize(20); ex.setQueueCapacity(100); ex.initialize(); return ex; }
Why not new Thread()? No pooling/reuse, no lifecycle management, no backpressure/queueing, resource exhaustion risk in production.
7. Concurrent Collections & Producer-Consumer
Concurrent Collections
ConcurrentHashMapBucket/node-level locking — thread-safe map, no full-map lock
CopyOnWriteArrayListCopies array on write — best when reads >> writes
ConcurrentLinkedQueueLock-free, non-blocking FIFO queue
BlockingQueueBlocks on put()/take() when full/empty — Producer-Consumer
ConcurrentSkipListMapThread-safe sorted map, concurrent version of TreeMap
Producer-Consumer (BlockingQueue)
BlockingQueue<Integer> q = new ArrayBlockingQueue<>(10); q.put(1); // producer, blocks if full q.take(); // consumer, blocks if empty
ConcurrentHashMap
ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>(); map.computeIfAbsent("k", k -> "v");
8. Synchronization Utilities
UtilityPurpose
CountDownLatchOne-time — main thread awaits N workers finishing (not reusable)
CyclicBarrierReusable — all threads wait for each other at a checkpoint
SemaphoreLimits N concurrent threads — DB pool, rate limiting
PhaserAdvanced reusable barrier with dynamic party registration
ExchangerTwo threads swap data at a synchronization point
CountDownLatch
CountDownLatch latch = new CountDownLatch(3); latch.countDown(); // per worker latch.await(); // main thread
Semaphore (Rate Limiting)
Semaphore sem = new Semaphore(5); sem.acquire(); try { /* limited resource */ } finally { sem.release(); }
CountDownLatch vs CyclicBarrier — CountDownLatch is one-time use, parent thread waits; CyclicBarrier is reusable, all threads wait for each other.
9. Fork-Join, Parallel Streams & CompletableFuture
CompletableFuture Chain (Aggregator Pattern)
supplyAsync()
thenApply()
thenCombine()
exceptionally()
Async Task → Transform → Combine Results → Handle Errors
CompletableFuture<User> u = CompletableFuture.supplyAsync( () -> userService.getUser()); CompletableFuture<Order> o = CompletableFuture.supplyAsync( () -> orderService.getOrders()); CompletableFuture.allOf(u, o).join();
ForkJoinPool & Parallel Stream
ForkJoinPoolDivide-and-conquer pool with work-stealing between idle threads
RecursiveTask<V>Fork-join task that returns a result
RecursiveActionFork-join task with no return value
Work StealingIdle worker threads "steal" tasks from busy threads' queues
parallelStream()Uses common ForkJoinPool internally — good for CPU-bound work only
Avoid parallelStream() for: DB Calls, External APIs, Small Collections.
10. ThreadLocal & Spring Boot @Async
ThreadLocal
ThreadLocal<T>Per-thread isolated copy of a variable — no sharing across threads
InheritableThreadLocalChild threads inherit parent's ThreadLocal value
MDC (Logging)Uses ThreadLocal to carry correlation/request-ID through logs
Use cases: User Context, Correlation ID, Request Tracking. Always call .remove() in thread pools to avoid leaks.
Spring Boot @Async
@EnableAsync @Async public CompletableFuture<String> process() { return CompletableFuture .completedFuture("Done"); }
⚠ Will @Async work in a same-class self-invocation call? NO — Spring AOP proxy is bypassed; the method must be called through the Spring-managed bean.
11. Thread Pool Sizing & Kafka Concurrency
Thread Pool Sizing (Frequently Asked)
CPU-Bound Tasks
Threads = CPU Cores + 1
e.g. heavy computation, encryption, image processing
I/O-Bound Tasks
Threads = Cores × (1 + Wait/Compute)
e.g. DB calls, REST API calls, file I/O — usually need larger pools
Kafka Consumer Concurrency (Partitions ≥ Consumers)
@KafkaListener(topics = "orders", concurrency = "3") // 6 Partitions, 3 Consumers Consumer-1 → P0, P1 Consumer-2 → P2, P3 Consumer-3 → P4, P5
One partition is consumed by exactly one consumer within a group — extra consumers beyond partition count sit idle.
12. Production Troubleshooting
High CPUThread dump + profiler to find hot loops/threads
DeadlockThread dump shows "waiting to lock" cycle
Thread DumpSnapshot of all thread states/stacks at a point in time
Heap DumpSnapshot of memory objects — for memory leak analysis
StarvationThread never scheduled — check fairness / priorities
Pool ExhaustionAll pool threads busy — queue grows, requests time out
13. Interview Comparisons & Must-Know Code Snippets
synchronizedReentrantLock
JVM managed, auto-releaseManual lock/unlock (try/finally)
No tryLock()tryLock() with timeout
Less flexibleFair locking, interruptible
wait()sleep()
Releases the lockKeeps the lock
Object classThread class
Needs synchronizedNo synchronized needed
HashMapConcurrentHashMap
Not thread-safeThread-safe, bucket-level locks
Race conditions possibleSafe concurrent access
CountDownLatchCyclicBarrier
One-time useReusable
Main thread waits for workersAll threads wait for each other
Runnable Task
class MyTask implements Runnable { public void run() { System.out.println("Running"); } }
Callable + Future
Callable<String> task = () -> "Success"; Future<String> f = executor.submit(task); String result = f.get(); // blocks
Synchronized Method / Block
public synchronized void increment() { count++; } synchronized(this) { count++; }
Volatile Flag (Safe Stop)
private volatile boolean running = true; // running = false; from another thread // visible immediately to the loop thread
AtomicInteger Counter
AtomicInteger count = new AtomicInteger(0); count.incrementAndGet(); count.getAndIncrement();
ExecutorService Basics
ExecutorService ex = Executors.newFixedThreadPool(10); ex.submit(task); ex.shutdown();
ThreadLocal Context
ThreadLocal<String> user = new ThreadLocal<>(); user.set("Pranik"); user.get(); user.remove(); // avoid leaks in pools
CompletableFuture Chain
CompletableFuture.supplyAsync(this::callService) .thenApply(this::process) .exceptionally(ex -> "Fallback");
14. Multithreading — 30-Second Interview Revision
Concurrency ≠ Parallelism (overlap vs simultaneous)
Thread: NEW→RUNNABLE→RUNNING→(BLOCKED/WAITING/TIMED_WAITING)→TERMINATED
Prefer Runnable/Callable over extending Thread
Race Condition = unsynchronized shared-state read-modify-write
volatile = visibility only, NOT atomicity
Atomic classes use CAS — lock-free thread safety
ReentrantLock > synchronized: tryLock(), fairness
Deadlock = circular wait on locks → prevent via lock ordering
wait() releases lock; sleep() keeps lock
Avoid new Thread() in enterprise code — use ExecutorService
CPU-bound pool size = cores + 1
I/O-bound pool size = cores × (1 + wait/compute)
parallelStream() uses common ForkJoinPool — avoid for I/O
CompletableFuture > Future: non-blocking, chainable
ConcurrentHashMap: bucket-level locks, no full-map lock
CopyOnWriteArrayList: best when reads >> writes
CountDownLatch = one-time; CyclicBarrier = reusable
Semaphore = limit N concurrent threads (DB pool, rate limit)
ThreadLocal = per-thread isolated data (context, correlation ID)
@Async fails on self-invocation — AOP proxy bypassed
Kafka: partitions ≥ consumers; extra consumers idle
Troubleshooting: thread dump for deadlock/blocking, heap dump for memory
Part II
Exception Handling
15. Exception Handling Basics & Throwable Hierarchy
Throwable Hierarchy
Object └── Throwable (message + cause + stack trace) ├── Error — serious JVM problems, usually unrecoverable └── Exception — application can handle/recover ├── Checked Exception — checked at compile time └── RuntimeException — Unchecked Exception, checked at runtime
Without exception handling: error occurs → program terminates. With it: error occurs → exception caught → alternative logic runs → application continues.
Error vs Exception
ErrorException
Serious JVM problem, app should not handleUnexpected but recoverable situation
OutOfMemoryError, StackOverflowError, NoClassDefFoundErrorIOException, SQLException, ArithmeticException, NullPointerException
Purpose of exception handling: maintain normal program flow, prevent crashes, improve reliability, meaningful error messages, simplify debugging.
16. Checked vs Unchecked Exceptions
Checked Exception
Checked AtCompile Time
HandlingCompiler forces try-catch OR throws
NatureRecoverable
ExamplesIOException, SQLException, ClassNotFoundException, FileNotFoundException, InterruptedException, ParseException
Unchecked Exception
Checked AtRuntime
HandlingCompiler does NOT force handling
NatureUsually a programming mistake
ExamplesNullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException, IllegalArgumentException, NumberFormatException, ClassCastException, ConcurrentModificationException
Real Project Scenarios
IOExceptionReading a CSV file
SQLExceptionDatabase query failure
InterruptedExceptionBackground job interrupted
NumberFormatExceptionInvalid user input
NullPointerExceptionMissing API response field
ArithmeticExceptionDivision by zero in business calculation
17. try / catch / finally — Execution Flow
BlockRule
tryContains risky code; only one try block before catch/finally
catchHandles a specific exception; can have multiple catch blocks, ordered specific → generic
finallyAlways executes (exception or not); used for cleanup — close resources, release connections
Multi-Catch (Java 7+)catch(IOException | SQLException e) — less code, better readability
Execution Flow
try
↓ No Exception
Skip catch → finally → Continue
↓ Exception Occurs
Matching catch → finally → Continue
return inside try: finally still executes, then the method returns. System.exit() terminates the JVM — finally will NOT execute. Only one finally is allowed per try.
final vs finally vs finalize()
finalKeyword — cannot change (variable/method/class)
finallyBlock — always executes
finalize()Method — called before GC, deprecated, don't use
18. throw vs throws & Exception Propagation
throw
TypeKeyword — actually throws one exception
UsedInside a method body, creates an exception object
Syntaxthrow new Exception(...);
throws
TypeDeclares possible exceptions in method signature
UsedCan declare multiple, does not itself throw anything
Syntaxvoid readFile() throws IOException
Exception Propagation Flow
main()
service()
repository()
Exception thrown
→ propagates back →
Handled at main()/service()
Checked exceptions must be handled or declared at every level. Unchecked exceptions automatically propagate until caught.
19. Custom & Business Exceptions
Custom Exception Hierarchy
Exception └── BusinessException ├── UserNotFoundException ├── PaymentFailedException └── CourseNotFoundException
Create custom exceptions for: User Not Found, Insufficient Balance, Course Already Exists, Certificate Expired, Invalid OTP, Payment Failed.
Checked Custom Exception
ExtendsException
HandlingCompiler forces handling, recoverable
Runtime Custom Exception
ExtendsRuntimeException
HandlingPreferred for business validation — Spring Boot standard
Technical vs Business Exception
TechnicalIOException, SQLException, Network Failure, Timeout
BusinessDuplicate User, Invalid Password, Invalid OTP, Course Closed
20. Try-With-Resources, Suppressed & Exception Chaining
Try-With-Resources (Java 7+)
Open Resource
Use Resource
Resource Automatically Closed (finally not required)
Works with AutoCloseable/Closeable: FileInputStream, BufferedReader, Scanner, Connection, PreparedStatement, ResultSet, Socket. Benefits: less boilerplate, no resource leaks, recommended for JDBC.
Suppressed Exception & Exception Chaining
Suppressed Exception → occurs when a primary exception already exists and another exception occurs while closing a resource; it gets attached to the primary exception Exception Chaining → wraps one exception inside another to preserve the original cause (e.g. SQLException → RepositoryException → ServiceException → Controller)
Why chaining? Preserve root cause, better debugging, layer separation — enterprise standard.
Stack Trace
Sequence of method calls leading to the exception. Read bottom → top; the root cause is usually the last "Caused by".
21. Spring Boot Exception Handling
Global Exception Flow
Client Request
Controller
Service
Repository
→ Exception →
Global Exception Handler
JSON Error Response → Client
Local vs Global Exception Handling
Local (try-catch)Global (@ControllerAdvice)
Inside method, repeated code, hard to maintainCentralized, reusable, recommended
@ControllerAdvice vs @RestControllerAdvice
@ControllerAdvice@RestControllerAdvice
MVC + REST, needs @ResponseBody for JSON= @ControllerAdvice + @ResponseBody, returns JSON automatically — preferred for REST APIs
@ResponseStatus vs ResponseStatusException
@ResponseStatusResponseStatusException
Static mapping on a custom exception classDynamic HTTP status without creating a custom exception class
@ExceptionHandler — Example Mappings
UserNotFoundException404
DuplicateUserException409
IllegalArgumentException / Validation Exception400
AccessDeniedException403
AuthenticationException401
Unhandled Exception500
ProblemDetail (Spring Boot 3 · RFC 9457) & Standard Error Response
ProblemDetail Fields
type · title · status · detail · instance
Standard, REST-friendly, extensible error format provided by Spring Boot 3.
Recommended Error Response Fields
timestamp · status · error · message · path · traceId · requestId · errors (validation)
22. Validation Exceptions & HTTP Status Cheat Sheet
Validation Flow
@RequestBody
@Valid
MethodArgumentNotValidException
Global Handler → Validation Errors
Common annotations: @NotNull @NotBlank @NotEmpty @Size @Email @Pattern @Positive @Min @Max @Past @Future
ExceptionOccurs When
MethodArgumentNotValidException@RequestBody validation fails
ConstraintViolationException@PathVariable / @RequestParam validation fails
BindExceptionObject binding fails (form data, query params)
HttpMessageNotReadableExceptionInvalid/malformed JSON, wrong data type
HttpRequestMethodNotSupportedExceptionWrong HTTP method (e.g. GET instead of POST)
NoHandlerFoundExceptionRequested URL not found → 404
HTTP Status Cheat Sheet
200OK
201Created
204No Content
400Bad Request
401Unauthorized
403Forbidden
404Not Found
405Method Not Allowed
409Conflict
422Unprocessable Entity (optional)
500Internal Server Error
503Service Unavailable
Real Project Scenarios
User RegistrationDuplicate Email → 409 Conflict
LoginInvalid Credentials → 401 Unauthorized
Certificate PortalCertificate Not Found → 404
Course EnrollmentCourse Full → 400 Bad Request
PaymentGateway Timeout → 503 Service Unavailable
DatabaseConstraint Violation → 409 Conflict
23. Best Practices & Anti-Patterns
✓ Best Practices
Catch specific exceptions first, most specific → most generic
Never catch Throwable; never ignore exceptions
Keep try blocks small; always close resources
Use try-with-resources for JDBC/file IO
Log exceptions properly; log once, handle once
Create business-specific exceptions; extend RuntimeException for business errors
Preserve root cause via exception chaining
Use @RestControllerAdvice + standard ErrorResponse DTO
Map correct HTTP status codes; validate input using @Valid
Don't expose internal stack trace to clients; include correlation/trace ID
✗ Anti-Patterns
✗ Catch Exception / Throwable everywhere
✗ Empty catch block
✗ Printing stack trace in production
✗ Using exceptions for normal control flow
✗ Throwing generic Exception
✗ Swallowing exceptions silently
✗ Returning null instead of throwing an exception
Logging strategy: Business Exception → WARN, Validation Error → INFO, Technical Exception → ERROR. Never log passwords, OTPs, JWTs, or other sensitive data.
24. Exception Handling — One-Liner Revision
Throwable → Parent of Errors & Exceptions
Error → JVM Problem
Exception → Recoverable Problem
Checked Exception → Compile Time
Unchecked Exception → Runtime
try → Risky Code
catch → Handle Exception
finally → Cleanup Block
Multi-Catch → One catch for multiple exceptions
throw → Explicitly throw exception
throws → Declare possible exception
Propagation → Travels to caller until handled
Custom Exception → Business-meaningful exception
Try-With-Resources → Auto resource cleanup
AutoCloseable → Interface enabling auto-close
Suppressed Exception → Exception during resource close
Exception Chaining → Wrap original exception (preserve cause)
Stack Trace → Method call history to the exception
@ControllerAdvice → Global exception handler
@RestControllerAdvice → REST global handler (JSON)
@ExceptionHandler → Handles a specific exception
@ResponseStatus → Static HTTP status
ResponseStatusException → Dynamic HTTP status
ProblemDetail → Standard Spring Boot 3 error format
MethodArgumentNotValidException → Request body validation
ConstraintViolationException → Parameter validation
AccessDeniedException → 403
AuthenticationException → 401
Global Handler → Central error management
final vs finally vs finalize() → constant / cleanup block / deprecated GC hook
25. Final Combined Revision Flow
15-Minute Multithreading Flow
Fundamentals → Thread Lifecycle
Thread Creation (Runnable/Callable)
Thread Safety (Sync/Volatile/Atomic/CAS)
Locking & Deadlock
Executor Framework & Thread Pools
Concurrent Collections & Sync Utilities
Fork-Join / CompletableFuture / @Async / Kafka
15-Minute Exception Handling Flow
Throwable Hierarchy → Checked/Unchecked
try / catch / finally
throw vs throws → Propagation
Custom Exception → Try-With-Resources
@ControllerAdvice → @ExceptionHandler
ProblemDetail → Validation Exceptions
Logging → Production Best Practices
Interviewers Expect You To Explain
✓ Thread Lifecycle & Internal Working of Executors ✓ Race Conditions & Synchronization Strategies ✓ Deadlock Causes & Prevention ✓ CompletableFuture / Parallel Streams Trade-offs ✓ Checked vs Unchecked Exception Design Choices ✓ Global Exception Handling in Spring Boot ✓ Exception Chaining & Root-Cause Preservation ✓ Real Production Troubleshooting (deadlocks, thread dumps, pool exhaustion)