When does java use CountDownLatch

Keywords: Programming Java

1. What is CountDownLatch

CountDownLatch was introduced in Java 1.5, along with the concurrency tool classes CyclicBarrier, Semaphore, ConcurrentHashMap, and BlockingQueue, which all exist under the java.util.concurrent package.CountDownLatch is a class that enables one thread to wait for other threads to finish their work before executing.For example, the main thread of the application wants to execute after the thread responsible for starting the framework service has started all the framework services.

CountDownLatch is implemented through a counter that starts with the number of threads.Each time a thread completes its own task, the value of the counter is reduced by 1.When the counter value reaches 0, it indicates that all threads have completed the task, and threads waiting on the latch can resume execution.

The pseudocode for CountDownLatch is as follows:

//Main thread start
//Create CountDownLatch for N threads
//Create and start N threads
//Main thread wait on latch
//N threads completes there tasks are returns
//Main thread resume execution

2. How CountDownLatch works

Constructors defined in the CountDownLatch.java class:

//Constructs a CountDownLatch initialized with the given count.
public void CountDownLatch(int count) {...}

The count in the constructor is actually the number of threads that need to wait for a latch.This value can only be set once, and CountDownLatch does not provide any mechanism to reset this count value.

The first interaction with CountDownLatch is when the main thread waits for another thread.The main thread must call the CountDownLatch.await() method immediately after starting another thread.This will block the main thread's operations in this way until the other threads have completed their respective tasks.

The other N threads must reference the blocked object because they need to notify the CountDownLatch object that they have completed their tasks.This notification mechanism is done through the CountDownLatch.countDown() method; every time this method is called, the count value initialized in the constructor is reduced by 1.So when all N threads call this method, count equals 0, and the main thread can resume executing its own tasks through the await() method.

3. Scenarios for use in real-time systems

  1. Maximum parallelism: Sometimes we want to start multiple threads at the same time to achieve maximum parallelism.For example, we want to test a single class.If we create a CountDownLatch with an initial count of 1 and let all threads wait on this lock, we can easily complete the test.We only need to call the countDown() method once to allow all waiting threads to resume execution at the same time.
  2. Wait for n threads to complete their tasks before starting execution: For example, the application startup class ensures that all N external systems are up and running before processing user requests.
  3. Deadlock detection: A very convenient use scenario is that you can use n threads to access shared resources, the number of threads is different during each test phase, and try to create a deadlock.

4. Examples of using CountDownLatch

Two classes, Task and WaitingTask, are used to simulate this; here, WaitingTask waits until all Task threads are executed before continuing.
Case study follows:

import java.util.concurrent.CountDownLatch;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.TimeUnit;  
  
class Task implements Runnable {  
    private static int counter = 0;  
    private final int id = ++counter;    //Set thread id  
  private final CountDownLatch latch;  //A reference to CountDownLatch must be present in the thread to notify that the WaitTask counter is already zero  
  
  public Task(CountDownLatch latch) {  
        this.latch = latch;  
    }  
  
    public void run() {  
        try {  
            doWork();      //Sleep for 1s here to complete the task for this thread  
  latch.countDown();  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
  
    public void doWork() throws InterruptedException {  
        TimeUnit.MILLISECONDS.sleep(200);  
        System.out.println(this \+ " completed");  
    }  
  
    @Override  
  public String toString() {  
        return "Task--" \+ id;  
    }  
}  
  
class WaitingTask implements Runnable {  
    private static int counter = 0;  
    private final int id = ++counter;   //Set thread id  
  private final CountDownLatch latch;  //A reference to CountDownLatch must be present in the thread to communicate with Task  
  
  public WaitingTask(CountDownLatch latch) {  
        this.latch = latch;  
    }  
  
    @Override  
  public void run() {  
        try {  
            latch.await();  
            System.out.println("Latch barrier passed for " \+ this);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
  
    @Override  
  public String toString() {  
        return "WaitingTask--" \+ id;  
    }  
}  
  
public class CountDownLatchDemo {  
    public static final int SIZE = 10;   //Define the number of threads waiting  
  
  public static void main(String args\[\]) throws Exception {  
        ExecutorService exe = Executors.newCachedThreadPool();  
        CountDownLatch latch = new CountDownLatch(SIZE);  
//        Five threads are blocked when they enter and wait for the other SIZE threads to finish executing before continuing  
  for (int i = 0; i < 5; i++) {  
            exe.execute(new WaitingTask(latch));  
        }  
  
//        Here are the other SIZE threads  
  for (int i = 0; i < SIZE; i++) {  
            exe.execute(new Task(latch));  
        }  
        exe.shutdown();  
    }  
}

Run result:

Task--2 completed
Task--8 completed
Task--4 completed
Task--9 completed
Task--10 completed
Task--1 completed
Task--3 completed
Task--5 completed
Task--7 completed
Task--6 completed
Latch barrier passed for WaitingTask--4
Latch barrier passed for WaitingTask--1
Latch barrier passed for WaitingTask--3
Latch barrier passed for WaitingTask--5
Latch barrier passed for WaitingTask--2

We clearly see that WaitingTask runs after the Task process.

Finally, you can ask yourself some questions to check if you have mastered the class.

  1. Explain the CountDownLatch concept?
    CountDownLatch is a synchronization tool class in the java.util.concurrent package that enables a thread to wait for other threads to finish their work before executing.

  2. Explain how CountDownLatch works
    CountDownLatch is implemented through a counter that starts with the number of threads.Each time a thread completes its own task, the value of the counter is reduced by 1.When the counter value reaches 0, it indicates that all threads have completed the task, and threads waiting on the latch can resume execution.

  3. What is the difference between CountDownLatch and Cyclic Barrier?
    CountDownLatch is not reusable, CyclicBarrier is reusable

  4. Give some examples of how CountDownLatch works?
    The above is given

  5. The main methods in the CountDownLatch class?

Posted by daria on Mon, 24 Feb 2020 15:15:01 -0800