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
- 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.
- 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.
- 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.
-
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. -
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. -
What is the difference between CountDownLatch and Cyclic Barrier?
CountDownLatch is not reusable, CyclicBarrier is reusable -
Give some examples of how CountDownLatch works?
The above is given -
The main methods in the CountDownLatch class?