你是否遇到這這樣一種狀況,咱們要舉行一個視頻會議,有若干的參會人員,須要等待全部的人員到齊後視頻會議才能開始。java
爲了解決這個問題,Java API提供了一個線程同步輔助類CountDownLatch,使用這個輔助類可讓線程等待其它線程完成一組操做後才能執行,不然就一直等待。這個類使用一個整形參數來初始化,這個整形參數表明着等待其餘線程的數量,使用await()方法讓線程開始等待其餘線程執行完畢,每個線程執行完畢後後調用countDown()方法,這個方法會讓CountDownLatch內部的計數器減1,當計數器變爲0的時候,CountDownLatch類將喚醒全部調用await()方法並進入WAITING狀態線程。併發
下面咱們來完成這個視頻會議的例子:dom
建立視頻會議線程類VideoConference,並聲明一個CountDownLatch屬性controller來控制視頻會議線程等待全部參會者到齊。會議線程啓動後會調用await()方法並進入等待狀態,每個參會者到達後代用arrive()方法,並把controller中的計數器減1,當計數器等於0的時候會議線程繼續執行。ide
public class VideoConference implements Runnable{ private final CountDownLatch controller; public VideoConference(int number) { controller = new CountDownLatch(number); } public void arrive(String name) { System.out.printf("%s has arrived.\n", name); controller.countDown(); System.out.printf("VideoConference: Waiting for %d participants.\n", controller.getCount()); } @Override public void run() { System.out.printf("VidwoConference: Initialization: %d participants.\n", controller.getCount()); try { controller.await(); System.out.printf("VidwoConference: All the participants have come.\n"); System.out.printf("VidwoConference: Let's start..."); } catch (InterruptedException e) { e.printStackTrace(); } } }
建立參會者線程類Participant,這個類持有會議類的引用,啓動後用一個隨機休眠時間來模擬與會者到達所需的時間,休眠結束後代用會議類的arrive(name)方法告訴會議類,與會者到達並把CountDownLatch計數器減1。this
public class Participant implements Runnable{ private String name; private VideoConference videoConference; public Participant(String name, VideoConference videoConference) { this.name = name; this.videoConference = videoConference; } @Override public void run() { long duration = (long) (Math.random() * 10); try { TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } videoConference.arrive(name); } }
實現主方法類,這裏咱們建立並移動一個視頻會議,規定參會者有10我的。而後咱們啓動10個參會者線程,當全部參會者都到達後,視頻會議開始執行。線程
public class Main { public static void main(String[] args) { VideoConference videoConference = new VideoConference(10); Thread threadConference = new Thread(videoConference); threadConference.start(); Thread[] threads = new Thread[10]; for (int i = 0; i < 10; i++) { threads[i] = new Thread(new Participant("P-" + i, videoConference)); } for (int i = 0; i < 10; i++) { threads[i].start(); } } }
查看控制檯日誌,咱們看到每次有一個參會者到達均可以調用getCount()方法來獲取計數器的值。日誌
VidwoConference: Initialization: 10 participants. P-0 has arrived. VideoConference: Waiting for 9 participants. P-4 has arrived. VideoConference: Waiting for 8 participants. P-2 has arrived. VideoConference: Waiting for 7 participants. P-5 has arrived. VideoConference: Waiting for 6 participants. P-8 has arrived. VideoConference: Waiting for 5 participants. P-3 has arrived. VideoConference: Waiting for 4 participants. P-6 has arrived. VideoConference: Waiting for 3 participants. P-1 has arrived. VideoConference: Waiting for 2 participants. P-7 has arrived. VideoConference: Waiting for 1 participants. P-9 has arrived. VideoConference: Waiting for 0 participants. VidwoConference: All the participants have come. VidwoConference: Let's start...
注意,CountDownLatch並非用來保護共享資源同步訪問的,而是用來控制併發線程等待的。而且CountDownLatch只容許進入一次,一旦內部計數器等於0,再調用這個方法將不起做用,若是還有第二次併發等待,你還得建立一個新的CountDownLatch。code