CountDownLatch introduction

Posted by PHPnewb_JavaAdept on Wed, 05 Jan 2022 11:21:47 +0100

1, What is CountDownLatch?

CountDownLatch is a synchronization tool class in Java util. In the current package, it is a tool class commonly used in JUC programming, allowing one or more threads to wait until other threads are running.
   its implementation is simply to give a specified value to the timer during initialization through a counter, and then in the sub thread, when the specified logic is executed, the counter will decrease by 1. When the counter is 0, the thread blocking and waiting will be awakened to resume execution.

2, Use example

   the use of CountDownLatch can generally be divided into two scenarios:

  • Scenario 1: multiple threads waiting for another
  • Scenario 2: one waiting for multiple threads

1. Scenario 1

  this is equivalent to a group of threads waiting for a specified time to execute concurrently (second kill) after they are ready. Just like when we were in high school, when the bell rang after early self-study, all the guys rushed to the canteen~

public class Main4 {


    public static void main(String[] args) throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(1);

        // Simple and direct new threads, or thread pools
        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ": Food is the most important thing for the people. We wait...");
                countDownLatch.await(); // Blocking, wait until the counter value is 0 before proceeding
                System.out.println(Thread.currentThread().getName() + ": Walking~");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"fool").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ": Excited heart, trembling hand, I also wait...");
                countDownLatch.await(); // Blocking, wait until the counter value is 0 before proceeding
                System.out.println(Thread.currentThread().getName() + ": Canteen, I'm coming~");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        },"son of a bitch").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ": Guys, get ready to copy this guy...");
                countDownLatch.await(); // Blocking, wait until the counter value is 0 before proceeding
                System.out.println(Thread.currentThread().getName() + ": go for it~");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        },"balut ").start();

        // After the main thread sleeps for 1 second, the counter decreases by 1
        Thread.sleep(1000);
        countDownLatch.countDown();

        System.out.println("The bell rings!");
    }

}

Execution results:

Fool: people live on food, we wait
Dog egg: excited heart, trembling hand, I wait
Hairy egg: brothers, prepare to copy the guy
The bell rings!
Fool: walk~
Boiled duck~
Dog egg: canteen, I'm coming~

2. Scenario 2

    sometimes concurrent tasks may have some before and after dependencies. For example, if I need to analyze the sales data of the current month, I read the data from different data tables through multiple threads, and then conduct unified analysis and processing after reading.

public class Main5 {


    public static void main(String[] args) throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(3);

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "Read order data...");
                Thread.sleep(700);
                System.out.println(Thread.currentThread().getName() + "Read complete!");
                countDownLatch.countDown(); // After the execution of the child thread, the count is decremented by 1
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "Read payment data...");
                Thread.sleep(500);
                System.out.println(Thread.currentThread().getName() + "Read complete!");
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t2").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "Read member data...");
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + "Read complete!");
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t3").start();

        // Block and wait for all threads to execute before proceeding
        countDownLatch.await();

        System.out.println("Data loading completed,Start analysis");
    }

}

Operation results:

t1 read order data
t2 read payment data
t3 read member data
t2 read completed!
t1 read complete!
t3 read complete!
Data loading is completed and analysis is started

3, Summary

  countdownlatch looks a bit like the join() method, but it is more flexible than join(). CountDownLatch can call n minus 1 operations in n threads, or n minus 1 operations in one thread. However, countdownlatch is one-time, and the initial value of the calculator can only be initialized once. When countdownlatch is used, it can not be used again, so there is a CyclicBarrier.

Topics: Multithreading CountDownLatch