1. Background:
- countDownLatch was introduced in Java 1.5 along with CyclicBarrier, Semaphore, concurrentHashMap, and BlockingQueue.
- Exists under the java.util.cucurrent package.
2. Concepts
- countDownLatch is a class that causes one thread to wait for other threads to execute after they have finished executing.
- This is achieved by a counter whose initial value is the number of threads.Each time a thread finishes executing, the value of the counter is -1. When the value of the counter is 0, it means that all threads have finished executing, and the threads waiting on the latch can resume working.
3. Source Code
//Constructor--argument count is count value public CountDownLatch(int count) { }; //The thread calling the await() method is suspended and waits until the count value is 0 to continue execution public void await() throws InterruptedException { }; //Similar to await(), execution continues until the count value has not changed to zero after a certain amount of time public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //Reduce the count value by 1 public void countDown() { };
4. Scenarios for using CountDownLatch
- A thread waits for n threads to finish executing before it starts running.Initializes the counter for CountDownLatch to new CountDownLatch(n), subtracts the counter by 1 countdownLatch.countDown() each time a task thread finishes executing, and awaits () on CountDownLatch when the counter value changes to 0.A typical scenario is when starting a service, the main thread needs to wait for multiple components to load before continuing.
- Implement maximum parallelism when multiple threads begin to execute tasks.Note that parallelism, not concurrency, emphasizes that multiple threads start execution at the same time.Similar to a race, put multiple threads at the start, wait for the gun to fire, and then run at the same time.By initializing a shared CountDownLatch(1), initializing its calculator to 1, multiple threads begin countdownlatch.await() before they start executing the task, and when the main thread calls countDown(), the counter becomes zero, and multiple threads wake up at the same time.
5. Notes
CountDownLatch is one-time, the value of the calculator can only be initialized once in the construction method, and there is no mechanism to set the value again. When CountDownLatch is used, it cannot be used again.
6. Use scenario instances
6.1 Scene 1
Main Thread Waits for Subthread Execution to Complete Execution
package com.xzy.ui.javalib.cucurrent.countdownlatch; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * CountdownLatch Use Scenario 1 * The main thread waits for the child thread to finish executing before executing */ public class CountdownLatchTest1 { public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(3); final CountDownLatch latch = new CountDownLatch(3); for (int i = 0; i < 3; i++) { Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println("Child Thread" + Thread.currentThread().getName() + "Start execution"); Thread.sleep((long) (Math.random() * 10000)); System.out.println("Child Thread" + Thread.currentThread().getName() + "Execution Complete"); latch.countDown();//This method is called by the current thread and the count is subtracted by one } catch (InterruptedException e) { e.printStackTrace(); } } }; service.execute(runnable); } try { System.out.println("Main Thread" + Thread.currentThread().getName() + "Waiting for sub-thread execution to complete..."); latch.await();//Block the current thread until the counter has a value of 0 System.out.println("Main Thread" + Thread.currentThread().getName() + "Start execution..."); } catch (InterruptedException e) { e.printStackTrace(); } } }
6.2 Use Scenario 2
In a 100-meter race, four athletes arrive at the court and wait for the referee's password. The referee gives a password. When the runner hears the password, he starts at the same time. When all the runners reach the end point, the referee makes a summary ranking.
package com.xzy.test.java.cucurrent.countdownlatch; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * CountDownLatch Use Scenario 2 * In the 100-meter race, four athletes arrived at the field and waited for the referee's password. The referee gave a password and the runner started at the same time. * When all players reach the end point, the referee summarizes the ranking */ public class CountdownLatchTest2 { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CountDownLatch cdOrder = new CountDownLatch(1); final CountDownLatch cdAnswer = new CountDownLatch(4); for (int i = 0; i < 4; i++) { Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println("Player" + Thread.currentThread().getName() + "Waiting for the referee to issue a password"); cdOrder.await(); System.out.println("Player" + Thread.currentThread().getName() + "The referee's password has been accepted"); Thread.sleep((long) (Math.random() * 10000)); System.out.println("Player" + Thread.currentThread().getName() + "Arrive at End"); cdAnswer.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }; service.execute(runnable); } try { Thread.sleep((long) (Math.random() * 10000)); System.out.println("Referee" + Thread.currentThread().getName() + "Upcoming Password"); cdOrder.countDown(); System.out.println("Referee" + Thread.currentThread().getName() + "Password sent, waiting for all players to reach the end point"); cdAnswer.await(); System.out.println("All the players reached the end point"); System.out.println("Referee" + Thread.currentThread().getName() + "Summary results ranking"); } catch (InterruptedException e) { e.printStackTrace(); } service.shutdown(); } }
7. Reference Articles
1.https://www.cnblogs.com/Lee_xy_z/p/10470181.html
2.https://www.jianshu.com/p/e233bb37d2e6