VOOZH about

URL: https://www.geeksforgeeks.org/interview-prep/java-concurrency-tools-modern-java-techniques-interview-questions/

⇱ Java Concurrency Tools & Modern Java Techniques Interview Questions - GeeksforGeeks


  • Courses
  • Tutorials
  • Interview Prep

Java Concurrency Tools & Modern Java Techniques Interview Questions

Last Updated : 25 Aug, 2025

This focuses on advanced interview questions around Java's concurrency utilities and modern parallelism techniques. It covers the Executor framework, thread pools, Callable, Future, and CompletableFuture for asynchronous programming. You’ll also explore synchronization tools like ReentrantLock, CountDownLatch, Semaphore, Phaser, and atomic classes, essential for writing scalable, non-blocking concurrent applications.

1. What is the difference between execute() and submit() in the Executor framework? In what scenarios would you prefer one over the other?

In Java, the Executor framework helps run tasks in a managed thread pool without manually creating threads. Two common ways to run tasks are execute() and submit(), which differ in result handling and exception management.

  • execute(): Runs a task without returning any result; exceptions may be lost.
  • submit(): Runs a task and returns a Future, letting you get the result or handle exceptions.

Use Case Example:

2. Explain the lifecycle of an ExecutorService. How do shutdown() and shutdownNow() differ, and what are their consequences?

An ExecutorService is a high-level API in Java that manages a pool of threads to run tasks efficiently. Knowing its lifecycle and shutdown methods is important to avoid leaving threads running or losing tasks.

  • shutdown(): Stops accepting new tasks but allows already submitted tasks to complete.
  • shutdownNow(): Tries to stop all running tasks immediately and returns tasks that were waiting to execute.

Pitfall: Calling shutdownNow() may interrupt important computation and lead to inconsistency if not handled.

3. How does Callable differ from Runnable? How do you retrieve results and handle exceptions from a Callable?

In Java, threads can perform tasks using Runnable or Callable. While both allow running code in parallel, Callable is more powerful because it can return results and throw checked exceptions, making it ideal for tasks where you need a response or error handling.

  • Runnable: Cannot return a result and cannot throw checked exceptions.
  • Callable: Returns a result (Future) and can throw exceptions.

Example:

4. How is a ThreadPoolExecutor configured in Java? How can misconfiguration lead to thread starvation or memory leaks?

A ThreadPoolExecutor allows you to manage a pool of threads efficiently, controlling how tasks are queued and executed. Proper configuration is essential to balance performance, avoid resource wastage, and prevent thread starvation or memory issues.

A ThreadPoolExecutor is configured using parameters like:

  • corePoolSize: Minimum number of threads to keep alive.
  • maximumPoolSize: Maximum number of threads allowed.
  • keepAliveTime: Time extra threads wait before termination.
  • workQueue: Queue to hold tasks before execution.
  • rejectionPolicy: Action when the queue is full.

Example:

5. What is the role of ScheduledExecutorService? How is scheduleAtFixedRate different from scheduleWithFixedDelay?

ScheduledExecutorService allows you to schedule tasks to run after a delay or repeatedly at fixed intervals, making it ideal for periodic or delayed tasks.

  • scheduleAtFixedRate: Runs tasks at fixed intervals, measured from the start of the previous execution.
  • scheduleWithFixedDelay: Runs tasks with a fixed delay after the previous execution completes.

Example:

Use case: FixedRate for heartbeats, FixedDelay for log processing

6. What is the Fork/Join framework in Java? How does RecursiveTask enable parallelism? Give an example.

The Fork/Join framework is used to split large tasks into smaller subtasks that run in parallel and then combine the results. RecursiveTask allows subtasks to return results which are merged to get the final output.

class SumTask extends RecursiveTask<Integer> { /* ... */ }

int sum = new ForkJoinPool().invoke(new SumTask(arr, 0, arr.length));

7. Explain the difference between synchronized and ReentrantLock. When should you prefer explicit locks?

In Java, both synchronized and ReentrantLock are used to achieve mutual exclusion, but ReentrantLock provides more advanced features for flexible concurrency control.

FeaturesynchronizedReentrantLock
InterruptibleNoYes
Try lockNoYes (tryLock())
Fairness controlNoYes
Condition objectNoYes

When to use ReentrantLock:

  • You need timeout or interruptible locks
  • You want fairness (FIFO order for threads)
  • You need multiple condition variables for complex coordination

8. What is the use of tryLock() in concurrent programming? How can it prevent deadlocks?

In Java, tryLock() is an advanced feature of ReentrantLock that tries to acquire a lock without blocking the thread. If the lock is unavailable, the thread can retry later or take an alternative action, rather than waiting indefinitely.

Example:

How it prevents deadlocks:

  • Avoids circular waits because a thread won’t block indefinitely on a lock.
  • Allows retry or backoff strategies for safe concurrency.

9. Compare ReadWriteLock and StampedLock. How does optimistic reading in StampedLock improve performance?

In Java, both ReadWriteLock and StampedLock allow multiple threads to read shared data concurrently while ensuring exclusive access for writers.

FeatureReadWriteLockStampedLock
Read lock typeBlockingOptimistic
Upgrading lockNoYes (carefully)

Example:

Optimistic reads reduce contention, especially in read-heavy systems.

10. What is CountDownLatch? How is it different from CyclicBarrier and Phaser?

In Java, CountDownLatch is a synchronization tool that allows threads to wait until a set of operations in other threads completes. It has a fixed count and cannot be reused once the count reaches zero.

  • CountDownLatch: Threads wait until the counter reaches zero; not reusable.
  • CyclicBarrier: Threads wait at a barrier point; reusable after barrier is tripped.
  • Phaser: Advanced multi-phase synchronization; reusable and supports dynamic registration of threads.

Example:

11. How does a Semaphore control access to a resource? Give a real-world example.

In Java, a Semaphore is a concurrency tool that controls access to a limited number of resources by allowing only a fixed number of threads to acquire the permit at a time.

  • Semaphore(n): Allows up to n threads to access the resource concurrently.
  • Threads must acquire() a permit before using the resource and release() it afterward.

Example:

Use Case: DB pool, printer access, API rate limiting

12. What are atomic classes in Java and how do they differ from locks? Explain CAS (Compare-And-Swap) with AtomicInteger.

In Java, atomic classes (like AtomicInteger, AtomicLong) provide thread-safe, lock-free operations on single variables using Compare-And-Swap (CAS). They ensure updates are atomic without blocking threads, unlike traditional locks.

  • CAS (Compare-And-Swap): Checks the current value and updates it only if it matches the expected value, preventing race conditions.

Example:

13. What problems can arise if AtomicInteger.incrementAndGet() is used along with non-atomic operations? Illustrate.

In multithreaded programming, AtomicInteger is often used to safely increment counters without explicit synchronization. However, even atomic operations can cause problems when combined with other non-atomic operations.

Example:


Output
2
4
6
8
10

Explanation:

  • counter.incrementAndGet(): thread-safe
  • nonAtomicValue = temp * 2: not thread-safe
  • Multiple threads can overwrite nonAtomicValue simultaneously, causing inconsistent results.

How to Fix

Wrap the combined operation in a synchronized block:

14. What is CompletableFuture? How does it support async programming in Java? Show task chaining and exception handling.

CompletableFuture is a Java class (from java.util.concurrent) that represents a future result of an asynchronous computation. You can start tasks in the background, chain multiple tasks together, and handle exceptions without blocking the main thread.

Example: Task Chaining

Output: Final Result: 13

Example: Exception Handling:

15. How do you combine multiple CompletableFutures and wait for all or any to complete?

In Java, CompletableFuture allows you to run multiple asynchronous tasks. Sometimes you need to wait for all tasks to finish or proceed as soon as any task completes. Java provides allOf() and anyOf() methods for this purpose.

1. Wait for All Tasks: CompletableFuture.allOf()


Output
Task 1, Task 2, Task 3
  • allOf() returns a CompletableFuture<Void> that completes when all provided futures complete.
  • You can then retrieve individual results using .join().

2. Wait for Any Task: CompletableFuture.anyOf()


Output
First completed: Fast Task

anyOf() returns a CompletableFuture<Object> that completes as soon as any one of the futures completes.

Comment