java併發程式設計(十)之執行緒倒計數鎖存器CountDownLatch
阿新 • • 發佈:2019-01-24
一、定義
一個同步輔助類,在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待。
用給定的計數 初始化 CountDownLatch。由於呼叫了 countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之後,會釋放所有等待的執行緒,await 的所有後續呼叫都將立即返回。這種現象只出現一次——計數無法被重置。如果需要重置計數,請考慮使用 CyclicBarrier。CountDownLatch 是一個通用同步工具,它有很多用途。將計數 1 初始化的 CountDownLatch 用作一個簡單的開/關鎖存器,或入口:在通過呼叫 countDown() 的執行緒開啟入口前,所有呼叫 await 的執行緒都一直在入口處等待。用 N 初始化的 CountDownLatch 可以使一個執行緒在 N 個執行緒完成某項操作之前一直等待,或者使其在某項操作完成 N 次之前一直等待。
CountDownLatch 的一個有用特性是,它不要求呼叫 countDown 方法的執行緒等到計數到達零時才繼續,而在所有執行緒都能通過之前,它只是阻止任何執行緒繼續通過一個 await。
二、用法
package cn.itcast.heima2; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountdownLatchTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); //建立一個作為開關的CountDownLatch final CountDownLatch cdOrder = new CountDownLatch(1); //建立一個指定執行緒數量才能 final CountDownLatch cdAnswer = new CountDownLatch(3); for(int i=0;i<3;i++){ Runnable runnable = new Runnable(){ public void run(){ try { System.out.println("執行緒" + Thread.currentThread().getName() + "正準備接受命令"); //使當前執行緒在鎖存器倒計數至零之前一直等待,除非執行緒被中斷. //不要求執行緒等到計數到達零時才繼續,只是在所有執行緒都能通過之前, //阻止執行緒繼續通過await. //說白了就是等cdOrder 這個計數器變為0,才繼續向下執行. cdOrder.await(); System.out.println("執行緒" + Thread.currentThread().getName() + "已接受命令"); //doSomeThing //... Thread.sleep((long)(Math.random()*10000)); System.out.println("執行緒" + Thread.currentThread().getName() + "迴應命令處理結果"); // 遞減鎖存器的計數,如果計數到達零,則釋放所有等待的執行緒. cdAnswer.countDown(); } catch (Exception e) { e.printStackTrace(); } } }; service.execute(runnable); } //主執行緒 try { Thread.sleep((long)(Math.random()*10000)); System.out.println("執行緒" + Thread.currentThread().getName() + "即將釋出命令"); //遞減鎖存器的計數,如果計數到達零,釋放所有等待的執行緒. //讓cdOrder 計數器減一,即變為0. cdOrder.countDown(); System.out.println("執行緒" + Thread.currentThread().getName() + "已傳送命令,正在等待結果"); //等待cdAnswer 計數器變為0,才向下執行. cdAnswer.await(); System.out.println("執行緒" + Thread.currentThread().getName() + "已收到所有響應結果"); } catch (Exception e) { e.printStackTrace(); } service.shutdown(); } }