Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • About
  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Interview Prep: 8+ Years (Senior & Lead)

Revise the 5–8 Years Tier

  • Revise: Advanced Core Java & Design Patterns (5–8 Years Tier)
  • Revise: Spring Boot Internals & Spring Security (5–8 Years Tier)
  • Revise: Microservices & Microservice Patterns (5–8 Years Tier)

Expert Core Java

  • Tricky Java Output, Operators & OOP Edge Cases — Interview Questions
  • Tricky Exceptions, Memory & Keyword Questions — Interview Questions
  • Classic Java Language Questions, Senior-Grade Answers — Interview Questions
  • Classic Collections, Threads & JDK APIs, Senior-Grade Answers — Interview Questions
  • Reflection, Dynamic Proxies, final & Modern OOP Design — Interview Questions

JVM Internals & Performance

  • Class Loading, Bytecode & Object Layout — Interview Questions
  • JIT Compilation & Runtime Optimisations — Interview Questions
  • Garbage Collectors Deep Dive — Interview Questions
  • JVM Tuning, GC Logs & Memory Footprint — Interview Questions
  • Memory Leaks, OutOfMemoryErrors & Profiling Tools — Interview Questions
  • Modules, Agents & Advanced JVM APIs — Interview Questions

Collections & Concurrency at Scale

  • Collections Internals & Complexity — Interview Questions
  • Iterators, Comparators & Ordering Contracts — Interview Questions
  • Concurrent Collections, Queues & Lock-Free Structures — Interview Questions
  • Threads, Executors & ForkJoin Internals — Interview Questions
  • Locks, Atomics, CAS & Synchronizers — Interview Questions
  • Java Memory Model, volatile, Fences & ThreadLocal — Interview Questions
  • Deadlock, Livelock, Starvation & Concurrent Design — Interview Questions
  • CompletableFuture, Parallel Streams & Non-Blocking I/O — Interview Questions

Modern Java (8 to 21+)

  • Lambdas & Functional Interfaces Internals — Interview Questions
  • Streams & Collectors Deep Dive — Interview Questions
  • Optional & Interface Default/Static Methods — Interview Questions
  • Java 9–25 Features & Virtual Threads — Interview Questions

Design Patterns, SOLID & Clean Code

  • Design Pattern Trade-offs & Combinations — Interview Questions
  • SOLID, Clean Code & Anti-Patterns — Interview Questions

Spring & Spring Boot Internals

  • IoC, Dependency Injection & Bean Lifecycle Internals — Interview Questions
  • Spring AOP, Proxies & @Async Internals — Interview Questions
  • Spring Configuration, Auto-Configuration & Custom Starters — Interview Questions
  • Spring MVC & REST Internals, Exception Frameworks — Interview Questions
  • Spring Security Advanced Internals — Interview Questions
  • Spring WebFlux, Reactor & R2DBC — Interview Questions
  • Spring Cloud, Observability & Distributed Tracing — Interview Questions
  • Spring Boot 3, Native Images & Production Scenarios — Interview Questions

JPA, Hibernate & Databases at Scale

  • Spring Data JPA — Queries, Projections, Custom Repositories & Locking — Interview Questions
  • JPA Entity Mapping, Associations & Cascades — Interview Questions
  • JPQL vs Native Queries in Depth — Interview Questions
  • Hibernate Caching — First-Level, Second-Level & Query Cache — Interview Questions
  • Lazy vs Eager Loading, LazyInitializationException & N+1 — Interview Questions
  • JPA Transactions, Propagation, Isolation & Dirty Checking — Interview Questions
  • SQL vs NoSQL, Indexing & Query Tuning — Interview Questions
  • Database Scaling, Replication, Pooling & Consistency Models — Interview Questions
  • Redis, Search, Time-Series, CDC & Transactional Data Modelling — Interview Questions

Testing Strategy & API Design

  • Spring Boot Test Slices, Context & Test Strategy — Interview Questions
  • Testing Web, Persistence, Security, Async & Messaging in Spring Boot — Interview Questions
  • JUnit 5 & Mockito, Advanced — Interview Questions
  • MockMvc, WebTestClient & Testcontainers in Depth — Interview Questions
  • REST Principles, Status Codes & Resource Design — Interview Questions
  • OpenAPI, Validation Errors, API Versioning & GraphQL — Interview Questions

Build, DevOps & Cloud

  • Maven & Gradle at Scale — Interview Questions
  • Git, CI/CD Pipelines & Release Safety — Interview Questions
  • Docker & Kubernetes for Java Engineers — Interview Questions
  • Quality Gates, Artifact Repositories & Secrets Management — Interview Questions
  • AWS Deployment & Scaling for Spring Boot — Interview Questions
  • Multi-Cloud Deployment, High Availability, Cost & Cloud Troubleshooting — Interview Questions
  • Protocols, Supply-Chain Security, SRE Metrics & Platform Engineering — Interview Questions

Kafka & Messaging

  • Kafka Internals & Delivery Semantics — Interview Questions
  • Spring Kafka — Error Handling, DLQs, Schemas & Operations — Interview Questions
  • RabbitMQ, JMS & Messaging Models — Interview Questions

Microservices & Architecture

  • Distributed Systems Fundamentals — CAP, Consistency, Availability & SLOs — Interview Questions
  • DDD, Hexagonal Architecture & Service Boundaries — Interview Questions
  • Event-Driven Architecture, CQRS, Event Sourcing, Sharding & Idempotency — Interview Questions
  • Rate Limiting, Resilience, Caching at Scale & Chaos Engineering — Interview Questions
  • Files, Documents & Internationalisation in Java Backends — Interview Questions
  • WebSockets, Schedulers, Notifications & Real-Time Pipelines — Interview Questions

System Design Scenarios

  • Booking Systems, CRS, Inventory & Concurrency Control — Interview Questions
  • Dynamic Pricing & Rule Engines — Interview Questions
  • Partner Integrations — OTA Sync, Retries, Webhooks, Reconciliation & Bulk Data — Interview Questions
  • Designing Caches & Rate Limiters — Interview Questions
  • Event-Driven Architecture, Kafka at Scale, IoT & Real-Time Pipelines — Interview Questions
  • Observability, Logging, Alerting & Audit Systems — Interview Questions
  • Multi-Tenant SaaS, Identity & Platform Services — Interview Questions
  • Search, Notifications, Chat, Fraud Detection & Workflows — Interview Questions
  • Extreme Scale, 99.99% Availability, DR & Project Deep-Dive Stories — Interview Questions

Security for Senior Engineers

  • Tokens, OAuth2 PKCE, Web Attacks & API Security — Interview Questions
  • TLS, mTLS, Zero Trust, Secrets, DDoS & Privacy Compliance — Interview Questions

AI & LLM Integration

  • LLM Integration in Java — Spring AI, Bedrock, Prompts, Streaming & Orchestration — Interview Questions
  • RAG, Embeddings, Vector Databases & Conversational Memory — Interview Questions
  • AI Security, Guardrails, Cost & Operations — Interview Questions

DSA Coding Round

  • Array Problems — Rotation, Subarrays, Intervals, In-Place Tricks — Interview Questions
  • String Problems & Sliding Window — Interview Questions
  • Backtracking & Recursion — Interview Questions
  • Linked Lists, LRU & LFU Caches — Interview Questions
  • Stacks, Queues & Monotonic Stacks — Interview Questions
  • Binary Trees & BSTs — Interview Questions
  • Graph Algorithms — Interview Questions
  • Dynamic Programming — Interview Questions
  • Heaps & Greedy Algorithms — Interview Questions
  • Bit Manipulation & Math — Interview Questions
  • Concurrency Coding Round — Thread Pool, Blocking Queue, Latch, Future, File Processor — Interview Questions
  • Low-Level Design (Machine Coding) Problems — Interview Questions

Leadership & Behavioural

  • Leadership Style, Motivation & Team Health — Interview Questions
  • Delivery, Planning & Decisions Under Uncertainty — Interview Questions
  • Problem Solving, Growth & Career Stories — Interview Questions
  • Stakeholder Communication, Ethics & Compliance — Interview Questions
  • Mentoring, Knowledge Sharing & Code Reviews — Interview Questions
  • Agile & Scrum Practices for Senior Engineers — Interview Questions
  • Architecture Decision-Making — Interview Questions
  • Conflict Resolution & Difficult Conversations — Interview Questions
Chaturmind
← Java Interview Prep: 8+ Years (Senior & Lead)

Revise the 5–8 Years Tier

  • Revise: Advanced Core Java & Design Patterns (5–8 Years Tier)
  • Revise: Spring Boot Internals & Spring Security (5–8 Years Tier)
  • Revise: Microservices & Microservice Patterns (5–8 Years Tier)

Expert Core Java

  • Tricky Java Output, Operators & OOP Edge Cases — Interview Questions
  • Tricky Exceptions, Memory & Keyword Questions — Interview Questions
  • Classic Java Language Questions, Senior-Grade Answers — Interview Questions
  • Classic Collections, Threads & JDK APIs, Senior-Grade Answers — Interview Questions
  • Reflection, Dynamic Proxies, final & Modern OOP Design — Interview Questions

JVM Internals & Performance

  • Class Loading, Bytecode & Object Layout — Interview Questions
  • JIT Compilation & Runtime Optimisations — Interview Questions
  • Garbage Collectors Deep Dive — Interview Questions
  • JVM Tuning, GC Logs & Memory Footprint — Interview Questions
  • Memory Leaks, OutOfMemoryErrors & Profiling Tools — Interview Questions
  • Modules, Agents & Advanced JVM APIs — Interview Questions

Collections & Concurrency at Scale

  • Collections Internals & Complexity — Interview Questions
  • Iterators, Comparators & Ordering Contracts — Interview Questions
  • Concurrent Collections, Queues & Lock-Free Structures — Interview Questions
  • Threads, Executors & ForkJoin Internals — Interview Questions
  • Locks, Atomics, CAS & Synchronizers — Interview Questions
  • Java Memory Model, volatile, Fences & ThreadLocal — Interview Questions
  • Deadlock, Livelock, Starvation & Concurrent Design — Interview Questions
  • CompletableFuture, Parallel Streams & Non-Blocking I/O — Interview Questions

Modern Java (8 to 21+)

  • Lambdas & Functional Interfaces Internals — Interview Questions
  • Streams & Collectors Deep Dive — Interview Questions
  • Optional & Interface Default/Static Methods — Interview Questions
  • Java 9–25 Features & Virtual Threads — Interview Questions

Design Patterns, SOLID & Clean Code

  • Design Pattern Trade-offs & Combinations — Interview Questions
  • SOLID, Clean Code & Anti-Patterns — Interview Questions

Spring & Spring Boot Internals

  • IoC, Dependency Injection & Bean Lifecycle Internals — Interview Questions
  • Spring AOP, Proxies & @Async Internals — Interview Questions
  • Spring Configuration, Auto-Configuration & Custom Starters — Interview Questions
  • Spring MVC & REST Internals, Exception Frameworks — Interview Questions
  • Spring Security Advanced Internals — Interview Questions
  • Spring WebFlux, Reactor & R2DBC — Interview Questions
  • Spring Cloud, Observability & Distributed Tracing — Interview Questions
  • Spring Boot 3, Native Images & Production Scenarios — Interview Questions

JPA, Hibernate & Databases at Scale

  • Spring Data JPA — Queries, Projections, Custom Repositories & Locking — Interview Questions
  • JPA Entity Mapping, Associations & Cascades — Interview Questions
  • JPQL vs Native Queries in Depth — Interview Questions
  • Hibernate Caching — First-Level, Second-Level & Query Cache — Interview Questions
  • Lazy vs Eager Loading, LazyInitializationException & N+1 — Interview Questions
  • JPA Transactions, Propagation, Isolation & Dirty Checking — Interview Questions
  • SQL vs NoSQL, Indexing & Query Tuning — Interview Questions
  • Database Scaling, Replication, Pooling & Consistency Models — Interview Questions
  • Redis, Search, Time-Series, CDC & Transactional Data Modelling — Interview Questions

Testing Strategy & API Design

  • Spring Boot Test Slices, Context & Test Strategy — Interview Questions
  • Testing Web, Persistence, Security, Async & Messaging in Spring Boot — Interview Questions
  • JUnit 5 & Mockito, Advanced — Interview Questions
  • MockMvc, WebTestClient & Testcontainers in Depth — Interview Questions
  • REST Principles, Status Codes & Resource Design — Interview Questions
  • OpenAPI, Validation Errors, API Versioning & GraphQL — Interview Questions

Build, DevOps & Cloud

  • Maven & Gradle at Scale — Interview Questions
  • Git, CI/CD Pipelines & Release Safety — Interview Questions
  • Docker & Kubernetes for Java Engineers — Interview Questions
  • Quality Gates, Artifact Repositories & Secrets Management — Interview Questions
  • AWS Deployment & Scaling for Spring Boot — Interview Questions
  • Multi-Cloud Deployment, High Availability, Cost & Cloud Troubleshooting — Interview Questions
  • Protocols, Supply-Chain Security, SRE Metrics & Platform Engineering — Interview Questions

Kafka & Messaging

  • Kafka Internals & Delivery Semantics — Interview Questions
  • Spring Kafka — Error Handling, DLQs, Schemas & Operations — Interview Questions
  • RabbitMQ, JMS & Messaging Models — Interview Questions

Microservices & Architecture

  • Distributed Systems Fundamentals — CAP, Consistency, Availability & SLOs — Interview Questions
  • DDD, Hexagonal Architecture & Service Boundaries — Interview Questions
  • Event-Driven Architecture, CQRS, Event Sourcing, Sharding & Idempotency — Interview Questions
  • Rate Limiting, Resilience, Caching at Scale & Chaos Engineering — Interview Questions
  • Files, Documents & Internationalisation in Java Backends — Interview Questions
  • WebSockets, Schedulers, Notifications & Real-Time Pipelines — Interview Questions

System Design Scenarios

  • Booking Systems, CRS, Inventory & Concurrency Control — Interview Questions
  • Dynamic Pricing & Rule Engines — Interview Questions
  • Partner Integrations — OTA Sync, Retries, Webhooks, Reconciliation & Bulk Data — Interview Questions
  • Designing Caches & Rate Limiters — Interview Questions
  • Event-Driven Architecture, Kafka at Scale, IoT & Real-Time Pipelines — Interview Questions
  • Observability, Logging, Alerting & Audit Systems — Interview Questions
  • Multi-Tenant SaaS, Identity & Platform Services — Interview Questions
  • Search, Notifications, Chat, Fraud Detection & Workflows — Interview Questions
  • Extreme Scale, 99.99% Availability, DR & Project Deep-Dive Stories — Interview Questions

Security for Senior Engineers

  • Tokens, OAuth2 PKCE, Web Attacks & API Security — Interview Questions
  • TLS, mTLS, Zero Trust, Secrets, DDoS & Privacy Compliance — Interview Questions

AI & LLM Integration

  • LLM Integration in Java — Spring AI, Bedrock, Prompts, Streaming & Orchestration — Interview Questions
  • RAG, Embeddings, Vector Databases & Conversational Memory — Interview Questions
  • AI Security, Guardrails, Cost & Operations — Interview Questions

DSA Coding Round

  • Array Problems — Rotation, Subarrays, Intervals, In-Place Tricks — Interview Questions
  • String Problems & Sliding Window — Interview Questions
  • Backtracking & Recursion — Interview Questions
  • Linked Lists, LRU & LFU Caches — Interview Questions
  • Stacks, Queues & Monotonic Stacks — Interview Questions
  • Binary Trees & BSTs — Interview Questions
  • Graph Algorithms — Interview Questions
  • Dynamic Programming — Interview Questions
  • Heaps & Greedy Algorithms — Interview Questions
  • Bit Manipulation & Math — Interview Questions
  • Concurrency Coding Round — Thread Pool, Blocking Queue, Latch, Future, File Processor — Interview Questions
  • Low-Level Design (Machine Coding) Problems — Interview Questions

Leadership & Behavioural

  • Leadership Style, Motivation & Team Health — Interview Questions
  • Delivery, Planning & Decisions Under Uncertainty — Interview Questions
  • Problem Solving, Growth & Career Stories — Interview Questions
  • Stakeholder Communication, Ethics & Compliance — Interview Questions
  • Mentoring, Knowledge Sharing & Code Reviews — Interview Questions
  • Agile & Scrum Practices for Senior Engineers — Interview Questions
  • Architecture Decision-Making — Interview Questions
  • Conflict Resolution & Difficult Conversations — Interview Questions
HomeLearnJava Interview PrepJava Interview Prep: 8+ Years (Senior & Lead)DSA Coding Round
✓ FreeAdvanced· 7 min read

Concurrency Coding Round — Thread Pool, Blocking Queue, Latch, Future, File Processor — Interview Questions

Hands-on Java concurrency implementations interviewers ask seniors to write — a custom thread pool, a bounded blocking queue, a countdown latch, a custom Future, and a concurrent file processor — with correct locking, conditions, interruption handling, and shutdown.

Published September 25, 2026


How to use this lesson

In concurrency coding rounds, correctness details are what get scored:

  • guard every shared state with one lock;
  • wait in a while loop (spurious wakeups);
  • handle InterruptedException properly (restore the flag, or propagate it);
  • signal after changing state;
  • support shutdown.

Say what you'd use in production (java.util.concurrent), then write the simplified version. Related implementations (thread-safe singleton, producer-consumer, deadlock, concurrent LRU, read-write lock, CompletableFuture, ForkJoinPool, and the atomic counter) are covered in the Senior concurrency chapter.

Q1. Design a bounded blocking queue.

Short answer: Use one ReentrantLock with two conditions, notFull and notEmpty, over a circular array:

  • put waits while the queue is full, inserts, then signals notEmpty;
  • take waits while it's empty, removes, then signals notFull.

(The alternative is synchronized with wait/notifyAll: simpler, but it wakes both producers and consumers.) In production, use ArrayBlockingQueue or LinkedBlockingQueue.

public final class BoundedBlockingQueue<E> {
    private final Object[] items; private int head, tail, count;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition(), notEmpty = lock.newCondition();
    public BoundedBlockingQueue(int capacity) { items = new Object[capacity]; }

    public void put(E e) throws InterruptedException {
        lock.lockInterruptibly();
        try {
            while (count == items.length) notFull.await();
            items[tail] = e; tail = (tail + 1) % items.length; count++;
            notEmpty.signal();
        } finally { lock.unlock(); }
    }
    @SuppressWarnings("unchecked")
    public E take() throws InterruptedException {
        lock.lockInterruptibly();
        try {
            while (count == 0) notEmpty.await();
            E e = (E) items[head]; items[head] = null; head = (head + 1) % items.length; count--;
            notFull.signal();
            return e;
        } finally { lock.unlock(); }
    }
}

Common trap: using if instead of while around await(). After waking up (spuriously, or after another thread consumed the item first), the condition must be re-checked.

Q2. Implement a custom thread pool.

Short answer: Use a fixed set of worker threads that loop on queue.take() and run the tasks.

  • Keep workers alive if a task throws (catch the exception inside the loop).
  • Shutdown: stop accepting tasks, and let the workers finish the queued ones. Use a poison pill, or a flag plus interruption. shutdownNow interrupts the workers.
  • A bounded queue with a rejection policy protects against overload.

In production, use ThreadPoolExecutor, which adds core and maximum sizes, keep-alive, thread factories and rejection handlers.

public final class SimpleThreadPool {
    private final BlockingQueue<Runnable> queue;
    private final List<Thread> workers = new ArrayList<>();
    private volatile boolean shutdown;

    public SimpleThreadPool(int threads, int queueCapacity) {
        queue = new ArrayBlockingQueue<>(queueCapacity);
        for (int i = 0; i < threads; i++) {
            Thread t = new Thread(this::runWorker, "pool-worker-" + i);
            workers.add(t); t.start();
        }
    }
    public void execute(Runnable task) {
        if (shutdown) throw new RejectedExecutionException("pool is shut down");
        if (!queue.offer(task)) throw new RejectedExecutionException("queue full");   // rejection policy
    }
    private void runWorker() {
        while (true) {
            Runnable task;
            try {
                task = shutdown ? queue.poll() : queue.take();       // drain remaining tasks after shutdown
            } catch (InterruptedException e) {
                if (shutdown) { task = queue.poll(); } else continue;
            }
            if (task == null) return;                                // queue drained and shut down
            try { task.run(); } catch (RuntimeException ex) { /* log; keep the worker alive */ }
        }
    }
    public void shutdown() { shutdown = true; workers.forEach(Thread::interrupt); }
    public void awaitTermination() throws InterruptedException { for (Thread t : workers) t.join(); }
}

Q3. Implement a countdown latch.

Short answer: Keep a counter guarded by a monitor. countDown() decrements it (never below 0), and calls notifyAll() when it reaches 0. await() waits while count > 0. It's one-shot: it can't be reset (that's what CyclicBarrier is for). The JDK's CountDownLatch is built on the AQS shared mode.

public final class SimpleLatch {
    private int count;
    public SimpleLatch(int count) { if (count < 0) throw new IllegalArgumentException(); this.count = count; }
    public synchronized void countDown() {
        if (count > 0 && --count == 0) notifyAll();
    }
    public synchronized void await() throws InterruptedException {
        while (count > 0) wait();
    }
    public synchronized boolean await(long timeout, TimeUnit unit) throws InterruptedException {
        long deadline = System.nanoTime() + unit.toNanos(timeout);
        while (count > 0) {
            long remaining = deadline - System.nanoTime();
            if (remaining <= 0) return false;
            TimeUnit.NANOSECONDS.timedWait(this, remaining);
        }
        return true;
    }
    public synchronized long getCount() { return count; }
}

Q4. Implement a custom Future.

Short answer: A future holds a state (pending, done, failed or cancelled) plus a result or an exception.

  • complete and completeExceptionally set it once and wake the waiters.
  • get() blocks while pending (with a timeout variant), and rethrows failures wrapped in ExecutionException.
  • Callbacks registered before completion run on completion; those registered afterwards run immediately.

This is what FutureTask and CompletableFuture do, with lock-free CAS operations.

public final class SimpleFuture<T> {
    private enum State { PENDING, DONE, FAILED, CANCELLED }
    private State state = State.PENDING; private T value; private Throwable error;
    private final List<Consumer<SimpleFuture<T>>> callbacks = new ArrayList<>();

    public boolean complete(T v)                   { return finish(State.DONE, v, null); }
    public boolean completeExceptionally(Throwable t) { return finish(State.FAILED, null, t); }
    public boolean cancel()                        { return finish(State.CANCELLED, null, new CancellationException()); }

    private boolean finish(State s, T v, Throwable t) {
        List<Consumer<SimpleFuture<T>>> toRun;
        synchronized (this) {
            if (state != State.PENDING) return false;         // complete only once
            state = s; value = v; error = t;
            notifyAll();
            toRun = List.copyOf(callbacks); callbacks.clear();
        }
        toRun.forEach(cb -> cb.accept(this));                 // run callbacks outside the lock
        return true;
    }
    public synchronized T get() throws InterruptedException, ExecutionException {
        while (state == State.PENDING) wait();
        return report();
    }
    public synchronized T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        long deadline = System.nanoTime() + unit.toNanos(timeout);
        while (state == State.PENDING) {
            long left = deadline - System.nanoTime();
            if (left <= 0) throw new TimeoutException();
            TimeUnit.NANOSECONDS.timedWait(this, left);
        }
        return report();
    }
    private T report() throws ExecutionException {
        if (state == State.CANCELLED) throw (CancellationException) error;
        if (state == State.FAILED) throw new ExecutionException(error);
        return value;
    }
    public void onComplete(Consumer<SimpleFuture<T>> cb) {
        synchronized (this) { if (state == State.PENDING) { callbacks.add(cb); return; } }
        cb.accept(this);
    }
    public synchronized boolean isDone() { return state != State.PENDING; }
}

Q5. Write a concurrent file processor.

Short answer: Example: count the words across many large files, or process each line of a huge file.

  • Parallelise across files, using an ExecutorService sized for the workload: I/O-bound work can use virtual threads (Java 21+), CPU-bound work should use about the number of cores.
  • Stream each file (Files.lines or a BufferedReader); never load huge files entirely into memory.
  • Aggregate thread-safely: a ConcurrentHashMap with merge or LongAdders, or per-task local maps merged at the end (less contention).
  • Handle errors per file (collect them, and don't abort everything), plus timeouts and cancellation.
  • Backpressure: for a single huge file, use a producer-consumer setup (a reader thread feeding a bounded queue to worker threads), or split the file by byte ranges, aligned to line boundaries.
  • Close resources with try-with-resources, and shut down the executor.
Map<String, Long> countWords(List<Path> files) throws InterruptedException {
    ConcurrentHashMap<String, LongAdder> counts = new ConcurrentHashMap<>();
    try (ExecutorService pool = Executors.newVirtualThreadPerTaskExecutor()) {    // Java 21; close() waits for tasks
        List<Future<?>> futures = new ArrayList<>();
        for (Path file : files) {
            futures.add(pool.submit(() -> {
                try (Stream<String> lines = Files.lines(file)) {
                    lines.flatMap(l -> Arrays.stream(l.split("\\W+")))
                         .filter(w -> !w.isBlank())
                         .forEach(w -> counts.computeIfAbsent(w.toLowerCase(), k -> new LongAdder()).increment());
                }
                return null;
            }));
        }
        for (Future<?> f : futures) {
            try { f.get(); } catch (ExecutionException e) { /* log the failed file; continue with the others */ }
        }
    }
    Map<String, Long> result = new HashMap<>();
    counts.forEach((w, adder) -> result.put(w, adder.sum()));
    return result;
}

Advertisement

Follow-up questions this topic invites — and their answers

Q: Why use signal() rather than signalAll() with separate conditions? A: With separate notFull and notEmpty conditions, every waiter on a condition is waiting for the same thing, so waking one is enough and avoids a thundering herd. With a single monitor (wait/notify), you need notifyAll, because producers and consumers share one wait set.

Q: How should a worker handle InterruptedException? A: Either propagate it, or restore the flag with Thread.currentThread().interrupt() and exit, so the code that owns the thread (the pool, during shutdown) sees the interruption. Swallowing it silently breaks cancellation.

Q: Why run future callbacks outside the lock? A: Callbacks are foreign code. Running them while holding the lock risks deadlocks (if they call back into the future or take other locks) and blocks other threads unnecessarily.

Q: LongAdder or AtomicLong for counters? A: LongAdder spreads updates across cells, so it's far faster under heavy write contention; its sum() isn't an atomic snapshot. AtomicLong suits low contention, or when you need compare-and-set or exact point-in-time values.

Advertisement

Previous

Bit Manipulation & Math — Interview Questions

Next

Low-Level Design (Machine Coding) Problems — Interview Questions

AI Tutor

Lesson: Concurrency Coding Round — Thread Pool, Blocking Queue, Latch, Future, File Processor — Interview Questions

Quick actions

AI responses can be inaccurate. Verify critical information.