CountDownLatch与CyclicBarrier的对比

CountDownLatch:

CountDownLatch通过计数器来实现,计数器表示线程的数量。每当一个线程执行结束后,计数器的值就会减1,并在await方法处阻塞。一旦计数器为0,所有阻塞的线程均被释放,await方法后所有后续动作都会开始执行。计数器无法被重置。

并发模拟CountDownLatch

 1 import java.util.concurrent.CountDownLatch;
 2 
 3 public class CountRunnable implements Runnable {
 4     private CountDownLatch countDownLatch;
 5 
 6     public CountRunnable(CountDownLatch countDownLatch) {
 7         this.countDownLatch = countDownLatch;
 8     }
 9 
10     @Override
11     public void run() {
12         try {
13             synchronized (countDownLatch) {
14                 countDownLatch.countDown();
15                 System.out.println("down latch count = " + countDownLatch.getCount());
16             }
17             countDownLatch.await();
18             System.out.println("current count = " + (5 - countDownLatch.getCount()));
19         } catch (InterruptedException e) {
20             e.printStackTrace();
21         }
22     }
23 }

 

 1 import java.util.concurrent.CountDownLatch;
 2 import java.util.concurrent.ExecutorService;
 3 import java.util.concurrent.Executors;
 4 
 5 public class CountDownTest {
 6     public static void main(String[] args) {
 7         ExecutorService pool = Executors.newCachedThreadPool();
 8         CountDownLatch cdl = new CountDownLatch(5);
 9         for (int i = 0; i < 5; i++) {
10             CountRunnable countRunnable = new CountRunnable(cdl);
11             pool.execute(countRunnable);
12         }
13     }
14 }

控制台输出:

down latch count = 4
down latch count = 3
down latch count = 2
down latch count = 1
down latch count = 0
current count = 5
current count = 5
current count = 5
current count = 5
current count = 5

 观察到线程countDownLatch.countDown()方法后阻塞在await方法处,当所有线程都执行countDownLatch.countDown()方法后,即计数器count减为0后,每个线程的await()方法就会立刻return,从而执行之后的方法

CyclicBarrier:

CyclicBarrier可以协同多个线程,每个线程到达这个屏障处时都会等待,直到所有线程都到达了这个屏障时,再一起继续执行后面的动作。

模拟CyclicBarrier

 1 import java.util.concurrent.CyclicBarrier;
 2 
 3 public class CyclicBarrierThread extends Thread {
 4     private CyclicBarrier cb;
 5 
 6     private int sleepSecond;
 7 
 8     public CyclicBarrierThread(CyclicBarrier cb, int sleepSecond) {
 9         this.cb = cb;
10         this.sleepSecond = sleepSecond;
11     }
12 
13     public CyclicBarrier getCb() {
14         return cb;
15     }
16 
17     public void setCb(CyclicBarrier cb) {
18         this.cb = cb;
19     }
20 
21     public int getSleepSecond() {
22         return sleepSecond;
23     }
24 
25     public void setSleepSecond(int sleepSecond) {
26         this.sleepSecond = sleepSecond;
27     }
28 
29     public void run() {
30         try {
31             System.out.println(this.getName() + "start run ...");
32             Thread.sleep(sleepSecond * 1000);
33             System.out.println(this.getName() + "start to wait, time is " + System.currentTimeMillis());
34             cb.await();
35             System.out.println(this.getName() + "end wait, time is " + System.currentTimeMillis());
36         } catch (Exception e) {
37             e.printStackTrace();
38         }
39     }
40 }

 

 1 import java.util.concurrent.CyclicBarrier;
 2 
 3 public class Test {
 4     public static void main(String[] args) throws Exception {
 5         Runnable runnable = new Runnable() {
 6             @Override
 7             public void run() {
 8                 System.out.println("CyclicBarrier的所有线程await()结束了,开始指定的Runnable运行, 时间为" + System.currentTimeMillis());
 9             }
10         };
11 
12         CyclicBarrier cb = new CyclicBarrier(3, runnable);
13         CyclicBarrierThread cbt0 = new CyclicBarrierThread(cb, 3);
14         CyclicBarrierThread cbt1 = new CyclicBarrierThread(cb, 6);
15         CyclicBarrierThread cbt2 = new CyclicBarrierThread(cb, 9);
16         cbt0.start();
17         cbt1.start();
18         cbt2.start();
19     }
20 }

控制台输出

Thread-1 start run ...
Thread-2 start run ...
Thread-0 start run ...
Thread-0 start to wait, time is 1575901627885
Thread-1 start to wait, time is 1575901630884
Thread-2 start to wait, time is 1575901633886
CyclicBarrier的所有线程await()结束了,开始指定的Runnable运行, 时间为1575901633886
Thread-2 end wait, time is 1575901633886
Thread-0 end wait, time is 1575901633886
Thread-1 end wait, time is 1575901633886

观察到所有线程都运行到了await()方法的时候,所有线程后面的代码以及指定的Runnable同时运行

 综上:

1.CountDownLatch本质是一个计数器,线程执行一次,计数器减一,只能单次使用;而CyclicBarrier类似阀门或者栅栏,需要所有线程都到达,然后才能继续执行,可以多次使用

2.CountDownLatch当调用countDown()方法后的计数器等于指定的线程数之后,可以唤起多个线程的任务;而CyclicBarrier当执行到await()方法的线程数量等于指定的parties数量之后,只能唤起一个BarrierAction
 
 
 
 
posted @ 2019-12-09 21:16  达摩克利斯之剑  阅读(173)  评论(0编辑  收藏  举报