Advanced Java October 06 ,2025

CountDownLatch in Java

Complete Guide with Custom Implementation

Introduction

In multithreading, sometimes we need a way for one or more threads to wait until a set of operations in other threads completes.
This is where CountDownLatch comes in handy.

A CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
It is part of the java.util.concurrent package.

Key Points:

  • CountDownLatch uses a count initialized during construction.
  • Threads wait until the count reaches zero.
  • Once count reaches zero, all waiting threads proceed.
  • Cannot be reused after count reaches zero.

How CountDownLatch Works

When threads call await(), they wait until the latch’s count reaches zero.
Other threads call countDown() to decrement the count.

When the count reaches zero, all waiting threads are released.

Syntax:

CountDownLatch latch = new CountDownLatch(int count);

Here:

  • count = number of times countDown() must be called before threads can proceed.

Example: Using CountDownLatch

Let’s create a scenario where a main thread waits for three worker threads to finish their tasks.

Code:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        int count = 3;
        CountDownLatch latch = new CountDownLatch(count);

        Runnable worker = () -> {
            System.out.println(Thread.currentThread().getName() + " is working...");
            try {
                Thread.sleep((long) (Math.random() * 3000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " finished work.");
            latch.countDown();
        };

        for (int i = 0; i < count; i++) {
            new Thread(worker).start();
        }

        System.out.println("Main thread is waiting for workers...");
        latch.await();
        System.out.println("All workers finished. Main thread proceeds.");
    }
}

Expected Output:

Main thread is waiting for workers...
Thread-0 is working...
Thread-1 is working...
Thread-2 is working...
Thread-1 finished work.
Thread-0 finished work.
Thread-2 finished work.
All workers finished. Main thread proceeds.

Key Methods in CountDownLatch

MethodDescription
await()Causes the current thread to wait until the latch reaches zero
countDown()Decrements the count
getCount()Returns the current count

Custom Implementation of CountDownLatch in Java

Now let’s build a step-by-step custom version of CountDownLatch.

Step 1 — Plan the Logic

Our custom latch needs:

  • A count variable initialized during construction.
  • A mechanism to make threads wait (wait() / notifyAll()).
  • A countDown() method to decrement count and notify waiting threads.

Step 2 — Create CustomCountDownLatch Class

public class CustomCountDownLatch {
    private int count;

    public CustomCountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count cannot be negative");
        this.count = count;
    }

    public synchronized void await() throws InterruptedException {
        while (count > 0) {
            wait();
        }
    }

    public synchronized void countDown() {
        if (count > 0) {
            count--;
        }
        if (count == 0) {
            notifyAll();
        }
    }

    public synchronized long getCount() {
        return count;
    }
}

Step 3 — Test CustomCountDownLatch

public class CustomCountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        int count = 3;
        CustomCountDownLatch latch = new CustomCountDownLatch(count);

        Runnable worker = () -> {
            System.out.println(Thread.currentThread().getName() + " is working...");
            try {
                Thread.sleep((long) (Math.random() * 3000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " finished work.");
            latch.countDown();
        };

        for (int i = 0; i < count; i++) {
            new Thread(worker).start();
        }

        System.out.println("Main thread is waiting for workers...");
        latch.await();
        System.out.println("All workers finished. Main thread proceeds.");
    }
}

Expected Output

Main thread is waiting for workers...
Thread-0 is working...
Thread-1 is working...
Thread-2 is working...
Thread-1 finished work.
Thread-0 finished work.
Thread-2 finished work.
All workers finished. Main thread proceeds.

 Full Code — Custom CountDownLatch Implementation in Java

// CustomCountDownLatch.java

/**
 * Custom implementation of a simplified CountDownLatch in Java.
 * This class allows one or more threads to wait until a set of operations
 * being performed in other threads completes.
 */
public class CustomCountDownLatch {
    private int count;

    /**
     * Constructor initializes the latch with the given count.
     * @param count number of times countDown() must be called before threads can proceed
     */
    public CustomCountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("Count cannot be negative");
        this.count = count;
    }

    /**
     * Causes the current thread to wait until the latch has counted down to zero.
     */
    public synchronized void await() throws InterruptedException {
        while (count > 0) {
            wait();  // Wait until notified that count reached 0
        }
    }

    /**
     * Decrements the count of the latch. 
     * When count reaches zero, all waiting threads are released.
     */
    public synchronized void countDown() {
        if (count > 0) {
            count--;
            System.out.println("Latch count decreased to: " + count);
        }

        if (count == 0) {
            notifyAll(); // Wake up all waiting threads
        }
    }

    /**
     * Returns the current count.
     */
    public synchronized long getCount() {
        return count;
    }
}

 Test Code — Using CustomCountDownLatch

// CustomCountDownLatchTest.java

public class CustomCountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        int count = 3; // Number of worker threads
        CustomCountDownLatch latch = new CustomCountDownLatch(count);

        Runnable worker = () -> {
            System.out.println(Thread.currentThread().getName() + " is working...");
            try {
                // Simulate variable work time
                Thread.sleep((long) (Math.random() * 3000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " finished work.");
            latch.countDown();
        };

        // Start multiple worker threads
        for (int i = 0; i < count; i++) {
            new Thread(worker, "Worker-" + i).start();
        }

        System.out.println("Main thread is waiting for workers to complete...");
        latch.await(); // Main thread waits here until count reaches 0
        System.out.println("All workers finished. Main thread proceeds.");
    }
}

🧾 Sample Output

Main thread is waiting for workers to complete...
Worker-0 is working...
Worker-1 is working...
Worker-2 is working...
Worker-1 finished work.
Latch count decreased to: 2
Worker-0 finished work.
Latch count decreased to: 1
Worker-2 finished work.
Latch count decreased to: 0
All workers finished. Main thread proceeds.

 Comparison: Custom vs Real CountDownLatch

FeatureCustomCountDownLatchjava.util.concurrent.CountDownLatch
Thread Coordination✅ Yes✅ Yes
Resettable❌ No❌ No
Thread Safety✅ Yes (via synchronized)✅ Yes (via AQS)
Reusability❌ No❌ No
Fairness Control❌ No✅ Managed by AQS
Performance⚙️ Moderate (synchronized)⚡ High (LockSupport + AQS)

 

Advantages of CustomCountDownLatch

  • Understands thread coordination deeply.
  • Can be modified for specific synchronization needs.
  • Simple and reusable logic for learning.

 Disadvantages

  • No fairness control.
  • Cannot reset (unlike CyclicBarrier).
  • No interruption handling unless manually implemented.

 Real-World Use Case

CustomCountDownLatch is useful for:

  • Waiting for initialization tasks before proceeding.
  • Waiting for all services to start before accepting requests.
  • Coordinating parallel tasks in batch processing.

Conclusion

CountDownLatch is a powerful tool for synchronization.
The custom implementation helps understand the core logic behind it — using wait() and notifyAll() to coordinate thread execution.

In production, always use java.util.concurrent.CountDownLatch for better performance and reliability.
But building a custom version improves understanding of multithreading fundamentals.

 

Next Blog-  Semaphore in Java

 

Sanjiv
0

You must logged in to post comments.

Related Blogs

Generics P...
Advanced Java August 08 ,2025

Generics Part- 2

Collection...
Advanced Java July 07 ,2025

Collections Framewor...

Mastering...
Advanced Java August 08 ,2025

Mastering Java Multi...

Annotation...
Advanced Java August 08 ,2025

Annotations

Java Multi...
Advanced Java August 08 ,2025

Java Multithreading...

Java Memor...
Advanced Java August 08 ,2025

Java Memory Manageme...

Java Lambd...
Advanced Java August 08 ,2025

Java Lambda Expressi...

Java Funct...
Advanced Java August 08 ,2025

Java Functional Inte...

Java Strea...
Advanced Java August 08 ,2025

Java Stream API

JDBC (Java...
Advanced Java August 08 ,2025

JDBC (Java Database...

JDBC (Java...
Advanced Java September 09 ,2025

JDBC (Java Database...

Annotation...
Advanced Java August 08 ,2025

Annotations

Generics
Advanced Java August 08 ,2025

Generics

Java I/O (...
Advanced Java August 08 ,2025

Java I/O (NIO)

Introducti...
Advanced Java September 09 ,2025

Introduction to Desi...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Other Prin...
Advanced Java September 09 ,2025

Other Principles Beh...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Builder De...
Advanced Java September 09 ,2025

Builder Design Patte...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Chain of R...
Advanced Java September 09 ,2025

Chain of Responsibil...

Command De...
Advanced Java September 09 ,2025

Command Design Patte...

Interprete...
Advanced Java September 09 ,2025

Interpreter Design P...

Iterator D...
Advanced Java September 09 ,2025

Iterator Design Patt...

Mediator D...
Advanced Java September 09 ,2025

Mediator Design Patt...

Memento De...
Advanced Java September 09 ,2025

Memento Design Patte...

Observer D...
Advanced Java September 09 ,2025

Observer Design Patt...

State Desi...
Advanced Java September 09 ,2025

State Design Pattern...

Strategy D...
Advanced Java September 09 ,2025

Strategy Design Patt...

Template M...
Advanced Java September 09 ,2025

Template Method Desi...

Visitor De...
Advanced Java September 09 ,2025

Visitor Design Patte...

Prototype...
Advanced Java September 09 ,2025

Prototype Design Pat...

Java 8+ Fe...
Advanced Java October 10 ,2025

Java 8+ Features

SOLID Prin...
Advanced Java October 10 ,2025

SOLID Principles in...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

How Iterat...
Advanced Java October 10 ,2025

How Iterators Work i...

How Concur...
Advanced Java October 10 ,2025

How ConcurrentHashMa...

Comparable...
Advanced Java October 10 ,2025

Comparable vs Compar...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Semaphore...
Advanced Java October 10 ,2025

Semaphore in Java

ExecutorSe...
Advanced Java October 10 ,2025

ExecutorService in J...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Producer-C...
Advanced Java October 10 ,2025

Producer-Consumer Pr...

Implementi...
Advanced Java October 10 ,2025

Implementing a Custo...

Busy Spin
Advanced Java October 10 ,2025

Busy Spin

Serializat...
Advanced Java October 10 ,2025

Serialization and De...

Segment Lo...
Advanced Java October 10 ,2025

Segment Locking in J...

Tree Bins...
Advanced Java October 10 ,2025

Tree Bins in Java

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Get In Touch

G06, Kristal Olivine Bellandur near Bangalore Central Mall, Bangalore Karnataka, 560103

+91-8076082435

techiefreak87@gmail.com