Java多執行緒與併發庫高階應用之倒計時計數器CountDownLatch
CountDownLatch類是一個倒計時計數器,在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待。用給定的計數初始化 CountDownLatch。由於呼叫了countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之後,會釋放所有等待的執行緒,await 的所有後續呼叫都將立即返回。
CountDownLatch 是一個通用同步工具,它有很多用途。將計數1初始化的 CountDownLatch 用作一個簡單的開/關鎖存器,或入口:在通過呼叫 countDown() 的執行緒開啟入口前,所有呼叫 await 的執行緒都一直在入口處等待。用N初始化的 CountDownLatch 可以使一個執行緒在N個執行緒完成某項操作之前一直等待,或者使其在某項操作完成N次之前一直等待。
CountDownLatch猶如比賽的發令官,多條執行緒猶如運動員。倒計時到零時一聲槍響,運動員開始比賽,即多條執行緒開始執行。
使用CountDownLatch很簡單,因為它只提供了一個構造器:
CountDownLatch(int count):構造一個用給定計數初始化的CountDownLatch。
線上程中呼叫CountDownLatch物件的await()方法,會使當前執行緒在鎖存器倒計數至零之前一直等待,除非執行緒被中斷。而呼叫countDown()方法會遞減鎖存器的計數,如果計數到達零,則釋放所有等待的執行緒。
見下面程式:啟動三個執行緒等待主執行緒釋出命令,主執行緒釋出命令後等待三個執行緒執行完後的反饋。
public class CountDownLatchDemo { public static void main(String[] args) { //執行緒池 ExecutorService pool = Executors.newCachedThreadPool(); //定義兩個倒計時計數器 //等待命令倒計時計數器 final CountDownLatch countOrder = new CountDownLatch(1); //等待反饋倒計時計數器 final CountDownLatch countAnswer = new CountDownLatch(3); //3個子執行緒 for(int i = 0; i < 3; i++){ Runnable target = new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + "-等待命令"); //等待countOrder為0時停止等待,向下執行 countOrder.await(); System.out.println(Thread.currentThread().getName() + "-得到命令,開始執行"); Thread.sleep((long)(Math.random()*10000)); System.out.println(Thread.currentThread().getName() + "-命令執行完成,迴應結果"); //將countAnswer減一 countAnswer.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }; pool.execute(target); } //主執行緒 try{ Thread.sleep((long)(Math.random()*10000)); System.out.println(Thread.currentThread().getName() + "-即將釋出命令"); //將countOrder減一 countOrder.countDown(); System.out.println(Thread.currentThread().getName() + "-已釋出命令,等待迴應"); //等待迴應 countAnswer.await(); System.out.println(Thread.currentThread().getName() + "-已收到所有迴應結果"); }catch(InterruptedException e) { e.printStackTrace(); } pool.shutdown(); } }
執行程式
看到3個子執行緒在接到主執行緒命令前都等待,當主執行緒呼叫了countDown() 方法後減為零,3個子執行緒開始執行,並且主執行緒等待子執行緒執行完後的迴應。3個子執行緒沒執行完一個呼叫countDown() 方法,當3個都執行完後,主執行緒收到迴應。