CountDownLatch of concurrent programming tool class

In daily coding, Java Concurrent Programming is indispensable. Try the following concurrent programming tool classes.

Today, let's review and learn CountDownLatch, an ox fork tool class.

Meet CountDownLatch

CountDownLatch is a synchronization tool class used to coordinate the synchronization between multiple threads, or to talk about the role of communication between threads (non mutually exclusive).

CountDownLatch enables a thread to wait for other threads to complete their work before continuing execution. It is implemented using a counter. The initial value of the counter is the number of threads. When each thread completes its task, the value of the counter will be reduced by one. When the counter value is 0, it means that all threads have completed some tasks, and then the threads waiting on CountDownLatch can resume executing the next tasks.

Use of CountDownLatch

The CountDownLatch class is very simple to use.

Class is located at:
java.util.concurrent.CountDownLatch

The following briefly introduces its construction method and common methods.

Construction method

CountDownLatch only provides one construction method:

// Count is the initial count value
public CountDownLatch(int count) {
  // ......
}

common method

//Common method 1: the thread calling await() method will be suspended, and it will wait until the count value is 0
public void await() throws InterruptedException {
  // ......
}   
 
// Common method 2: similar to await(), but the execution will continue if the count value does not change to 0 after the timeout
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { 
  // ......
}
 
// Common method 3: reduce the count value by 1
public void countDown() {
  // ......
}  

Application scenario of CountDownLatch

Let's consider a scenario: after a user successfully places an order for a commodity, we will send various messages to the user to prompt the user that the purchase is successful, such as e-mail, wechat message, SMS, etc. After all messages are sent successfully, we record a message in the background to indicate success.

Of course, we can use single thread to complete each operation one by one, as shown in the following figure:

But this will be very inefficient. How to solve the problem of low efficiency of single thread? Of course, through multithreading.

Using multithreading will also encounter a problem. Before the sub thread messages are sent, the main thread may have printed "all messages have been sent", which is certainly wrong logically. We expect that the main thread will print the message after all the sub threads send the message. How to implement it? CountDownLatch can solve this kind of problem.

We use code to implement the above requirements.

import java.util.concurrent.*;
 
public class OrderServiceDemo {
 
    public static void main(String[] args) throws InterruptedException {
        System.out.println("main thread: Success to place an order");
 
        int count = 3;
        CountDownLatch countDownLatch = new CountDownLatch(count);
 
        Executor executor = Executors.newFixedThreadPool(count);
        executor.execute(new MessageTask("email", countDownLatch));
        executor.execute(new MessageTask("wechat", countDownLatch));
        executor.execute(new MessageTask("sms", countDownLatch));
 
        // The main thread is blocked and waits for all child threads to send messages
        countDownLatch.await();
        // All child threads have finished sending messages, the counter is 0, and the main thread resumes
        System.out.println("main thread: all message has been sent");
    }
 
    static class MessageTask implements Runnable {
        private String messageName;
        private CountDownLatch countDownLatch;
 
        public MessageTask(String messageName, CountDownLatch countDownLatch) {
            this.messageName = messageName;
            this.countDownLatch = countDownLatch;
        }
 
        @Override
        public void run() {
            try {
                // Thread send message
                System.out.println("Send " + messageName);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } finally {
                // The finished message counter is decremented by 1
                countDownLatch.countDown();
            }
        }
    }
}

Program running results:

main thread: Success to place an order
Send email
Send wechat
Send sms
main thread: all message has been sent

From the running results, we can see that the main thread prints after all sub threads send messages, which is in line with our expectations.

CountDownLatch restrictions

CountDownLatch is one-time. The value of the calculator can only be initialized once in the construction method. After that, there is no mechanism to set the value again. When CountDownLatch is used, it cannot be used again.

Have you learned? We'll talk about the remaining concurrency tool classes later. Let's wait and see~

Keywords: Java Back-end

Added by ron8000 on Wed, 27 Oct 2021 11:53:53 +0300