http://www.wtoutiao.com/p/1b4Lvvv.html
http://www.jb51.net/article/34729.htm
http://blog.csdn.net/lantian0802/article/details/9720993
http://aaron-han.iteye.com/blog/1591755
例子
1.CountDownLatch減計數,CyclicBarrier加計數。
2.CountDownLatch是一次性的,CyclicBarrier可以重用。
1、CountDownLatch
一個非常典型的應用場景是:有一個任務想要往下執行,但必須要等到其他的任務執行完畢后才可以繼續往下執行。假如我們這個想要繼續往下執行的任務調用一個CountDownLatch對象的await()方法,其他的任務執行完自己的任務后調用同一個CountDownLatch對象上的countDown()方法,這個調用await()方法的任務將一直阻塞等待,直到這個CountDownLatch對象的計數值減到0為止。
用法:用給定的計數初始化CountDownLath。調用countDown()方法計數減 1,在計數被減到 0之前,調用await方法會一直阻塞。減為 0之后,則會迅速釋放所有阻塞等待的線程,並且調用await操作會立即返回。
ps:CountDownLath計數無法被重置,如果需要重置計數,請考慮使用CyclicBarrier.
有五個人,一個裁判。這五個人同時跑,裁判開始計時,五個人都到終點了,裁判喊停,然后統計這五個人從開始跑到最后一個撞線用了多長時間。
1 import java.util.concurrent.CountDownLatch; 2 3 public class Race { 4 5 public static void main(String[] args) { 6 final int num = 5; 7 final CountDownLatch begin = new CountDownLatch(1); 8 final CountDownLatch end = new CountDownLatch(num); 9 10 for (int i = 0; i < num; i++) { 11 new Thread(new AWorker(i, begin, end)).start(); 12 } 13 14 // judge prepare... 15 try { 16 Thread.sleep((long) (Math.random() * 5000)); 17 } catch (InterruptedException e1) { 18 e1.printStackTrace(); 19 } 20 21 System.out.println("judge say : run !"); 22 begin.countDown(); 23 long startTime = System.currentTimeMillis(); 24 25 try { 26 end.await(); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } finally { 30 long endTime = System.currentTimeMillis(); 31 System.out.println("judge say : all arrived !"); 32 System.out.println("spend time: " + (endTime - startTime)); 33 } 34 35 } 36 37 } 38 39 class AWorker implements Runnable { 40 final CountDownLatch begin; 41 final CountDownLatch end; 42 final int id; 43 44 public AWorker(final int id, final CountDownLatch begin, 45 final CountDownLatch end) { 46 this.id = id; 47 this.begin = begin; 48 this.end = end; 49 } 50 51 @Override 52 public void run() { 53 try { 54 System.out.println(this.id + " ready !"); 55 begin.await(); 56 // run... 57 Thread.sleep((long) (Math.random() * 10000)); 58 } catch (Throwable e) { 59 e.printStackTrace(); 60 } finally { 61 System.out.println(this.id + " arrived !"); 62 end.countDown(); 63 } 64 } 65 66 }
輸出:

4 ready ! 1 ready ! 3 ready ! 2 ready ! judge say : run ! 1 arrived ! 4 arrived ! 0 arrived ! 2 arrived ! 3 arrived ! judge say : all arrived ! spend time: 9636
CountDownLatch強調的是一個線程(或多個)需要等待另外的n個線程干完某件事情之后才能繼續執行。 上述例子,main線程是裁判,5個AWorker是跑步的。運動員先准備,裁判喊跑,運動員才開始跑(這是第一次同步,對應begin)。5個人誰跑到終點了,countdown一下,直到5個人全部到達,裁判喊停(這是第二次同步,對應end),然后算時間。
2、使用cyclicbarrier
定義:是一個同步輔助類,它允許一組線程互相等待,直到到達某個公共的屏障點,所有線程一起繼續執行或者返回。一個特性就是CyclicBarrier支持一個可選的Runnable命令,在一組線程中的最后一個線程到達之后,該命令只在每個屏障點運行一次。若在繼續所有參與線程之前更新此共享狀態,此屏障操作很有用。
用法:用計數 N 初始化CyclicBarrier, 每調用一次await,線程阻塞,並且計數+1(計數起始是0),當計數增長到指定計數N時,所有阻塞線程會被喚醒。繼續調用await也將迅速返回。
規定五個人只要都跑到終點了,大家可以喝啤酒。但是,只要有一個人沒到終點,就不能喝。 這里也沒有要求大家要同時起跑
1 import java.util.concurrent.BrokenBarrierException; 2 import java.util.concurrent.CyclicBarrier; 3 4 public class Beer { 5 6 public static void main(String[] args) { 7 final int count = 5; 8 final CyclicBarrier barrier = new CyclicBarrier(count, new Runnable() { 9 @Override 10 public void run() { 11 System.out.println("drink beer!"); 12 } 13 }); 14 15 // they do not have to start at the same time... 16 for (int i = 0; i < count; i++) { 17 new Thread(new Worker(i, barrier)).start(); 18 } 19 } 20 21 } 22 23 class Worker implements Runnable { 24 final int id; 25 final CyclicBarrier barrier; 26 27 public Worker(final int id, final CyclicBarrier barrier) { 28 this.id = id; 29 this.barrier = barrier; 30 } 31 32 @Override 33 public void run() { 34 try { 35 System.out.println(this.id + "starts to run !"); 36 Thread.sleep((long) (Math.random() * 10000)); 37 System.out.println(this.id + "arrived !"); 38 this.barrier.await(); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } catch (BrokenBarrierException e) { 42 e.printStackTrace(); 43 } 44 } 45 }
輸出:

0starts to run ! 2starts to run ! 1starts to run ! 3starts to run ! 4starts to run ! 1arrived ! 3arrived ! 2arrived ! 0arrived ! 4arrived ! drink beer!
CyclicBarrier強調的是n個線程,大家相互等待,只要有一個沒完成,所有人都得等着。正如上例,只有5個人全部跑到終點,大家才能開喝,否則只能全等着。
這樣應該就清楚一點了,對於CountDownLatch來說,重點是那個“一個線程”, 是它在等待, 而另外那N的線程在把“某個事情”做完之后可以繼續等待,可以終止。而對於CyclicBarrier來說,重點是那N個線程,他們之間任何一個沒有完成,所有的線程都必須等待。