How do I use CountDownLatch to wait for other threads to finish?

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

How It Works

  • A CountDownLatch is initialized with a given count.
  • Each time one of the threads completes its task, it calls countDown(), which decreases the count by 1.
  • The threads waiting on this latch call await(). These threads remain blocked until the count reaches zero.
  • Once the count reaches zero, all waiting threads are unblocked, and they can proceed.

Example: Using CountDownLatch

Below is an example to demonstrate how to use CountDownLatch to make one thread wait for three other threads to finish:

Code Example

package org.kodejava.util.concurrent;

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) {
        // Initialize CountDownLatch with a count of 3
        CountDownLatch latch = new CountDownLatch(3);

        // Create three worker threads
        for (int i = 1; i <= 3; i++) {
            new Thread(new Worker(i, latch)).start();
        }

        System.out.println("Main thread is waiting for workers to finish...");

        try {
            // The main thread waits for the latch count to reach zero
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("All workers have finished. Main thread resumes.");
    }
}

class Worker implements Runnable {
    private int id;
    private CountDownLatch latch;

    public Worker(int id, CountDownLatch latch) {
        this.id = id;
        this.latch = latch;
    }

    @Override
    public void run() {
        System.out.println("Worker " + id + " started.");
        try {
            // Simulating work with sleep
            Thread.sleep((long) (Math.random() * 3000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Worker " + id + " finished.");

        // Decrement the latch count when work is done
        latch.countDown();
    }
}

Output

The output of the program will be as follows (the order might vary due to thread scheduling):

Main thread is waiting for workers to finish...
Worker 1 started.
Worker 2 started.
Worker 3 started.
Worker 1 finished.
Worker 3 finished.
Worker 2 finished.
All workers have finished. Main thread resumes.

Explanation

  1. CountDownLatch latch = new CountDownLatch(3);
    • Initializes a latch with a count of 3, meaning 3 decrements are required for the latch to reach zero.
  2. latch.countDown();
    • This is called by each worker thread after completing its task to decrement the latch count by 1.
  3. latch.await();
    • The main thread calls this method and waits until the count of the latch becomes zero. Once it’s zero, the main thread resumes execution.
  4. Threads finish their tasks in parallel (order is not guaranteed, as shown in the output), and the latch ensures the main thread waits until all workers are done.

Keynotes

  • CountDownLatch cannot be reused once the count reaches zero. For reusable functionality, consider using CyclicBarrier or Phaser.
  • It’s thread-safe and can be used across multiple threads.
  • Always handle InterruptedException properly when using await().

This synchronization tool is highly useful in scenarios where you need multiple threads to finish their tasks before proceeding to the next step in your program!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.