CountDownLatch和CyclicBarriar是java.util.concurrent包下面提供的多線程同步工具,二者有點類似,至關於計數器,可是用處仍是有區別的。java
CountDownLatch:用於在完成一組正在其它線程中執行的操做以前,它容許一個或多個線程一直等待,await()表示等待,等到其它線程所有執行結束後(即經過countDown()方法來減數,計數爲0,即其它線程執行完畢)而後繼續執行,示例代碼:多線程
public static void main(String[] args) { //該計數器初始值1,用於主線程發送命令 final CountDownLatch latch1 = new CountDownLatch(1); //該計數器初始值爲2,用於響應命令接受完成 final CountDownLatch latch2 = new CountDownLatch(2); //建立一個大小爲2線程池 ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < 2; i++) { executor.submit(new Runnable() { public void run() { try { System.out.println("線程" + Thread.currentThread().getName() + "正準備接受命令"); //等待主線程發送命令 latch1.await(); System.out.println("線程" + Thread.currentThread().getName() + "已接受命令"); Thread.sleep((long) (Math.random() * 10000)); System.out.println("線程" + Thread.currentThread().getName() + "迴應命令處理結果"); //命令接受完畢,返回給主線程,latch2減1。 latch2.countDown(); } catch (Exception e) { e.printStackTrace(); } } }); } try { Thread.sleep((long) (Math.random() * 10000)); System.out.println("線程" + Thread.currentThread().getName() + "即將發佈命令"); //發送命令,latch1計數減1 latch1.countDown(); System.out.println("線程" + Thread.currentThread().getName() + "已發送命令,正在等待響應"); //命令發送後處於等待狀態,其它線程所有響應完成,也就是latch2.countDown(),再繼續執行 latch2.await(); System.out.println("線程" + Thread.currentThread().getName() + "已收到全部響應結果"); } catch (Exception e) { e.printStackTrace(); } //關閉線程池 executor.shutdown(); }
CyclicBarriar:用於多個線程在一個指定的公共屏障點(或者說集合點)相互等待,await()方法表明屏障點,每次調用await(),計數(建立CyclicBarriar對象時傳入int類型的參數,表示初始計數)減一,直到減到0後,表示全部線程都抵達,而後開始執行後面的任務,示例代碼:dom
public static void main(String[] args) throws Exception { //建立CyclicBarrier對象並設置2個公共屏障點 final CyclicBarrier barrier = new CyclicBarrier(2); //建立大小爲2的線程池 ExecutorService executor = Executors.newFixedThreadPool(2); for (int i = 0; i < 2; i++) { executor.submit(new Runnable() { public void run() { try { Thread.sleep((long)(Math.random()*10000)); System.out.println("線程" + Thread.currentThread().getName() + "即將到達集合地點1,當前已有" + barrier.getNumberWaiting() + "個已經到達,正在等候"); //若是沒有達到公共屏障點,則該線程處於阻塞狀態,若是達到公共屏障點則全部處於等待的線程都繼續往下運行 barrier.await(); System.out.println("線程" + Thread.currentThread().getName() + "經過集合地點1"); Thread.sleep((long)(Math.random()*10000)); System.out.println("線程" + Thread.currentThread().getName() + "即將到達集合地點2,當前已有" + barrier.getNumberWaiting() + "個已經到達,正在等候"); barrier.await(); System.out.println("線程" + Thread.currentThread().getName() + "經過集合地點2"); } catch (Exception e) { e.printStackTrace(); } } }); } //關閉線程池 executor.shutdown(); }
注意:觀察CyclicBarrier的使用能夠發現,它計數減至0後,計數器會被重置,能夠再次使用,可能這也是它被定義爲Cyclic(週期的、循環的)緣由,這個是和CountDownLatch區別的地方。工具