Java多線程與並發庫高級應用之倒計時計數器


CountDownLatch 類是一個倒計時計數器,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。用給定的計數初始化 CountDownLatch。由於調用了countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之后,會釋放所有等待的線程,await 的所有后續調用都將立即返回。
CountDownLatch 是一個通用同步工具,它有很多用途。將計數1初始化的 CountDownLatch 用作一個簡單的開/關鎖存器,或入口:在通過調用 countDown() 的線程打開入口前,所有調用 await 的線程都一直在入口處等待。用N初始化的 CountDownLatch 可以使一個線程在N個線程完成某項操作之前一直等待,或者使其在某項操作完成N次之前一直等待。
CountDownLatch猶如比賽的發令官,多條線程猶如運動員。倒計時到零時一聲槍響,運動員開始比賽,即多條線程開始運行。

使用CountDownLatch很簡單,因為它只提供了一個構造器:
CountDownLatch(int count):構造一個用給定計數初始化的CountDownLatch。

在線程中調用CountDownLatch對象的await()方法,會使當前線程在鎖存器倒計數至零之前一直等待,除非線程被中斷。而調用countDown()方法會遞減鎖存器的計數,如果計數到達零,則釋放所有等待的線程。

見下面程序:啟動三個線程等待主線程發布命令,主線程發布命令后等待三個線程運行完后的反饋。
[java] view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. public class CountDownLatchDemo {  
  2.   
  3.     public static void main(String[] args) {  
  4.           
  5.         //線程池  
  6.         ExecutorService pool = Executors.newCachedThreadPool();  
  7.         //定義兩個倒計時計數器  
  8.         //等待命令倒計時計數器  
  9.         final CountDownLatch countOrder = new CountDownLatch(1);  
  10.         //等待反饋倒計時計數器  
  11.         final CountDownLatch countAnswer = new CountDownLatch(3);  
  12.           
  13.         //3個子線程  
  14.         for(int i = 0; i < 3; i++){  
  15.             Runnable target = new Runnable() {  
  16.                 @Override  
  17.                 public void run() {  
  18.                     try {  
  19.                         System.out.println(Thread.currentThread().getName() +   
  20.                                 "-等待命令");  
  21.                         //等待countOrder為0時停止等待,向下執行  
  22.                         countOrder.await();  
  23.                           
  24.                         System.out.println(Thread.currentThread().getName() +   
  25.                                 "-得到命令,開始執行");  
  26.                         Thread.sleep((long)(Math.random()*10000));  
  27.                         System.out.println(Thread.currentThread().getName() +   
  28.                                 "-命令執行完成,回應結果");  
  29.                         //將countAnswer減一  
  30.                         countAnswer.countDown();  
  31.                     } catch (InterruptedException e) {  
  32.                         e.printStackTrace();  
  33.                     }  
  34.                       
  35.                 }  
  36.             };  
  37.             pool.execute(target);  
  38.         }  
  39.           
  40.         //主線程  
  41.         try{  
  42.             Thread.sleep((long)(Math.random()*10000));  
  43.             System.out.println(Thread.currentThread().getName() +   
  44.                     "-即將發布命令");  
  45.             //將countOrder減一  
  46.             countOrder.countDown();  
  47.             System.out.println(Thread.currentThread().getName() +   
  48.                     "-已發布命令,等待回應");  
  49.             //等待回應  
  50.             countAnswer.await();  
  51.             System.out.println(Thread.currentThread().getName() +   
  52.                     "-已收到所有回應結果");  
  53.         }catch(InterruptedException e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.           
  57.         pool.shutdown();  
  58.     }  
  59.   
  60. }  

運行程序


看到3個子線程在接到主線程命令前都等待,當主線程調用了countDown() 方法后減為零,3個子線程開始運行,並且主線程等待子線程運行完后的回應。3個子線程沒運行完一個調用countDown() 方法,當3個都運行完后,主線程收到回應。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM