CountDownLatch and cyclicBarrier are both multithreaded utility classes under the java.util.concurrent package.
literally
- CountDown represents a subtraction count and Latch represents the Latch, which opens when the count is zero
- A cyclicBarrier is a circle of obstacles.
Both classes imply that the corresponding thread will do its work before moving on to the next step, i.e. when everyone is ready. However, the biggest difference between the two is that the next action is carried out differently.
The implementer of the countDownLatch action is the “current thread” and the cyclicBarrier is another thread.
For example:
For CountDwonLatch, using king of Glory as an example, the other threads are the players and the current thread is the thread that controls the start of the game. The current thread is in wait state, meaning the game cannot start. When all the players are ready, the game can begin.
- ‘waiting for all players to be ready
- Player0 is ready, in 1.235s
- Player2 is ready, in 1.279s
- Player3 is ready, taking 1.358s
- Player1 is ready, taking 2.583s
- Start the game ‘
CountDownLatch’s code:
import java.util.Random; import java.util.concurrent.CountDownLatch; public class CountDownLatchTest { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(4); for(int i = 0; i < latch.getCount(); i++){ new Thread(new MyThread(latch), "player"+i).start(); } system.out.println (" waiting for all players to be ready "); latch.await(); System.out.println(" start game "); } private static class MyThread implements Runnable{ private CountDownLatch latch ; public MyThread(CountDownLatch latch){ this.latch = latch; } @Override public void run() { try { Random rand = new Random(); int randomNum = rand.nextInt((3000 - 1000) + 1) + 1000; // Generate a random integer between 1000 and 3000 thread. sleep(randomNum); Println (thread.currentThread ().getName()+" ready "+((double)randomNum/1000)+"s"); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); }}}}Copy the code
As for CyclicBarrier, take company activities as an example. Assume that a company requires all employees to carry out a team-building activity, and the content of the activity is to climb over three obstacles. Each person takes different time to climb over the obstacles, but the rules of the game require all employees to climb over the current obstacle before they can climb over the next obstacle. By analogy, each player participating in an activity is an “other thread,” and the program ends when everyone has cleared all the obstacles. The current thread may have ended, cyclicBarrier regardless of the current thread’s execution state.
We use code to simulate the above process. We’ve got three employees and three obstacles. As you can see, all the employees climbed over the first obstacle before starting to climb over the second one. Here is the result:
- main function is finished.
- Team mate 1, cleared the 0th obstacle in 1.432 seconds
- Teammate 0, cleared the 0th obstacle in 1.465 seconds
- Team mate 2, cleared the 0th obstacle in 2.26 seconds
- Team mate 1, cleared the first obstacle in 1.542 seconds
- Teammate 0, through the first obstacle, took 2.154 seconds
- Team mate 2, cleared the first obstacle in 2.556s
- Team mate 1, cleared the second obstacle in 1.426 seconds
- Team mate 2, through the second obstacle, took 2.603 seconds
- Teammate 0, through the second obstacle, using 2.784s
Code:
package com.huai.thread; import java.util.Random; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierTest { public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(3); for(int i = 0; i < barrier.getParties(); I ++){new Thread(new MyRunnable(barrier), "mate "+ I).start(); } System.out.println("main function is finished."); } private static class MyRunnable implements Runnable{ private CyclicBarrier barrier; public MyRunnable(CyclicBarrier barrier){ this.barrier = barrier; } @Override public void run() { for(int i = 0; i < 3; i++) { try { Random rand = new Random(); int randomNum = rand.nextInt((3000 - 1000) + 1) + 1000; // Generate a random integer between 1000 and 3000 thread. sleep(randomNum); Println (thread.currentThread ().getName() +" + I +")+ (((double)randomNum/1000)+"s"); this.barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } } }Copy the code
Conclusion: Both CountDownLatch and cyclicBarrier have multiple threads waiting for synchronization before starting the next action, but the next action of countDwonLatch is performed by the current thread and is not repeatable. The next action of cyclicBarrier is performed by “other threads” themselves, which is characterized by repeated actions.