Logo

dev-resources.site

for different kinds of informations.

Using CountDownLatch in Java: A Deep Dive with Code Examples and Demos

Published at
12/19/2024
Categories
codeproject
java
concurrentsynchroniz
Author
anh_trntun_4732cf3d299
Author
22 person written this
anh_trntun_4732cf3d299
open
Using CountDownLatch in Java: A Deep Dive with Code Examples and Demos

1. Understanding CountDownLatch in Java

CountDownLatch is a part of the java.util.concurrent package and is used to synchronize one or more threads, forcing them to wait until a set of operations being performed in other threads completes. It's initialized with a count, and every time a thread completes its task, it decrements this count. Once the count reaches zero, the waiting threads are released.

1.1 What is CountDownLatch?

Image

CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations in other threads completes. Imagine you have multiple services that must be started before your main application can begin. With CountDownLatch , you can make the main thread wait until all services are up and running.

1.2 How Does CountDownLatch Work?

Image

The working mechanism of CountDownLatch revolves around a counter initialized to a specific value. Each time a thread completes its execution, it calls the countDown() method, which decrements the counter. When the counter reaches zero, the await() method releases all waiting threads, allowing them to proceed.

2. Reasons to Use CountDownLatch

CountDownLatch can be immensely beneficial in various scenarios where thread synchronization is needed. Here are some key reasons to use CountDownLatch in your Java applications:

2.1 Coordinating a Start of a Set of Threads

Image

In a scenario where you have multiple threads that need to wait for each other to start simultaneously, CountDownLatch can be a good solution. For example, you might want to start multiple services at the same time and have them work together seamlessly.

import java.util.concurrent.CountDownLatch;

public class Service implements Runnable {
    private final CountDownLatch latch;

    public Service(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void run() {
        try {
            System.out.println("Service " + Thread.currentThread().getName() + " is starting...");
            Thread.sleep(2000); // Simulating service initialization
            latch.countDown(); // Reducing count
            System.out.println("Service " + Thread.currentThread().getName() + " has started.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Application {
    public static void main(String[] args) {
        int numberOfServices = 3;
        CountDownLatch latch = new CountDownLatch(numberOfServices);

        for (int i = 0; i < numberOfServices; i++) {
            new Thread(new Service(latch)).start();
        }

        try {
            latch.await(); // Waiting for all services to complete
            System.out.println("All services are up, Application is starting now...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

Service Thread-0 is starting...
Service Thread-1 is starting...
Service Thread-2 is starting...
Service Thread-0 has started.
Service Thread-1 has started.
Service Thread-2 has started.
All services are up, Application is starting now...
Enter fullscreen mode Exit fullscreen mode

2.2 Dividing a Task into Several Parts

Image

Sometimes, a big task needs to be divided into smaller tasks that can be executed in parallel. Once all these sub-tasks are completed, the main thread can continue further processing. CountDownLatch makes this possible by allowing multiple threads to signal that their part of the work is done.

3. Using CountDownLatch for Multi-Phase Tasks

CountDownLatch is often used when you have multiple phases in a task, where each phase requires several threads to complete before moving on to the next phase. For example, in a simulation involving multiple processes, each phase could require all processes to synchronize at the end before moving on.

3.1 Multi-Phase Task Example

Consider a simulation where we need to perform multiple phases, and each phase involves several threads completing a task. Once all threads complete a phase, they can move to the next phase.

import java.util.concurrent.CountDownLatch;

public class PhaseTask implements Runnable {
    private final CountDownLatch latch;
    private final int phase;

    public PhaseTask(CountDownLatch latch, int phase) {
        this.latch = latch;
        this.phase = phase;
    }

    @Override
    public void run() {
        try {
            System.out.println("Thread " + Thread.currentThread().getName() + " is working on phase " + phase);
            Thread.sleep(1000); // Simulating task execution
            latch.countDown();
            System.out.println("Thread " + Thread.currentThread().getName() + " completed phase " + phase);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class MultiPhaseApplication {
    public static void main(String[] args) throws InterruptedException {
        int phases = 3;
        int threadsPerPhase = 5;

        for (int phase = 1; phase <= phases; phase++) {
            CountDownLatch latch = new CountDownLatch(threadsPerPhase);
            for (int i = 0; i < threadsPerPhase; i++) {
                new Thread(new PhaseTask(latch, phase)).start();
            }
            latch.await(); // Wait for all threads to complete the phase
            System.out.println("Phase " + phase + " completed. Moving to next phase...");
        }

        System.out.println("All phases are completed.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

Thread Thread-0 is working on phase 1
...
Phase 1 completed. Moving to next phase...
...
All phases are completed.
Enter fullscreen mode Exit fullscreen mode

3.2 Advantages of Using CountDownLatch

  • Simplicity : CountDownLatch offers a straightforward mechanism to synchronize threads.
  • Reusability : It can be used for multiple threads and in various situations, from waiting for services to start to completing phases in complex simulations.
  • Reliability : With a well-defined lifecycle and clear operations, CountDownLatch minimizes the risks of concurrency bugs.

4. Conclusion

CountDownLatch is a powerful utility in Java’s concurrency library, helping developers handle complex synchronization scenarios. By coordinating multiple threads efficiently, it simplifies code and improves reliability. Whether you need to manage service startups, divide tasks into parts, or synchronize multi-phase tasks, CountDownLatch is a robust choice.

If you have any questions or thoughts, feel free to leave a comment below!

Read posts more at : Using CountDownLatch in Java: A Deep Dive with Code Examples and Demos

codeproject Article's
30 articles in total
Favicon
Default Methods in Java
Favicon
Secrets of Java's String Pool
Favicon
Reasons Why Docker Runs Natively on Linux but Needs Virtualization on Windows
Favicon
Secrets of URIs, URLs, and URNs: Understanding Their Differences and Uses
Favicon
When Should You Use Threads in Java?
Favicon
Secrets of Distributed Locks
Favicon
Understanding the High Water Mark
Favicon
Ways to Speed Up Spring Boot Application Startup Time
Favicon
Mastering Java Generics: A Comprehensive Guide with Code Examples
Favicon
Understanding and Managing Tablespace in MySQL
Favicon
Handling the "Forwarded" Header in Spring Boot Applications
Favicon
Secrets Behind Deleting or Updating Records in PostgreSQL
Favicon
Strategies to Optimize PostgreSQL Performance Using VACUUM
Favicon
Techniques for Storing JSON Documents in PostgreSQL
Favicon
Methods for Storing Boolean Values in MySQL
Favicon
Relational Database Partition with Example
Favicon
Techniques for Leveraging ReBAC: A Comprehensive Guide
Favicon
How Does CAPTCHA Work?
Favicon
Secure User Passwords in a Database
Favicon
Tips to Avoid NullPointerException in Java
Favicon
Methods for Efficient Large File Processing in Spring Boot
Favicon
Master Local Variable Type Inference in Java: A Guide to Using var Effectively
Favicon
Understanding JWE: Structure, Operations, Advantages, Disadvantages, and How to Create One
Favicon
Reasons Why Rainbow Table Attacks Are Dangerous and How Salting Passwords Protects Against Them
Favicon
OSI Model Overview
Favicon
Understanding Runnable and Callable in Java: Examples and Code Demos
Favicon
Methods to Optimize Database Queries Using Query Hints in Spring Data JPA
Favicon
Techniques for Managing Session, Cookie, JWT, and SSO
Favicon
Using CountDownLatch in Java: A Deep Dive with Code Examples and Demos
Favicon
Tips for Saving Redis Memory: Essential Techniques for Efficient Resource Management

Featured ones: