CountdownLatch相当于一个倒计时的计数器,当计数到达0时,等待这个计数器的线程就开始执行。

下面通过代码看一下CountdownLatch的执行效果。

  • 1-1 一个CountdownLatch的例子
 
  
  1. import java.util.concurrent.CountDownLatch; 
  2. import java.util.concurrent.ExecutorService; 
  3. import java.util.concurrent.Executors; 
  4.  
  5. public class CountdownLatchTest { 
  6.     public static void main(String[] args) { 
  7.         ExecutorService service = Executors.newCachedThreadPool(); 
  8.         final CountDownLatch cdOrder = new CountDownLatch(1);//计数器的初始值为1 
  9.         final CountDownLatch cdAnswer = new CountDownLatch(3);//计数器的初始值为3    
  10.         for(int i=0;i<3;i++){//启动3个线程 
  11.             Runnable runnable = new Runnable(){ 
  12.                     public void run(){ 
  13.                     try { 
  14.                         System.out.println("线程" + Thread.currentThread().getName() +  
  15.                                 "正准备接受命令");                      
  16.                         cdOrder.await();//3个线程都在等待计数器,当计数为0时,都开始往下执行 
  17.                         System.out.println("线程" + Thread.currentThread().getName() +  
  18.                         "已接受命令");                                
  19.                         Thread.sleep((long)(Math.random()*10000));   
  20.                         System.out.println("线程" + Thread.currentThread().getName() +  
  21.                                 "回应命令处理结果");                         
  22.                         cdAnswer.countDown();//每个线程结束的时候把计数器减1                       
  23.                     } catch (Exception e) { 
  24.                         e.printStackTrace(); 
  25.                     }                
  26.                 } 
  27.             }; 
  28.             service.execute(runnable); 
  29.         }        
  30.         try {//主线程 
  31.             Thread.sleep((long)(Math.random()*10000)); 
  32.          
  33.             System.out.println("线程" + Thread.currentThread().getName() +  
  34.                     "即将发布命令");                       
  35.             cdOrder.countDown();//将计数器的计数减1 
  36.             System.out.println("线程" + Thread.currentThread().getName() +  
  37.             "已发送命令,正在等待结果"); 
  38.             //主线程在等待另外一个计数器(cdAnswer)为0,当为0时,开始向下执行。它(cdAnswer)的初始值为3, 
  39.             
 
  
  1. cdAnswer.await();  
            System.out.println("线程" + Thread.currentThread().getName() +               "已收到所有响应结果");             } catch (Exception e) {              e.printStackTrace();          }                         service.shutdown();      } 

上述CountdownLatch的代码例子中,有两个计数器

 
  
  1. final CountDownLatch cdOrder = new CountDownLatch(1); 

相当于在运动会上发布信号的指挥员,指挥员一吹哨子,3个“运动员”(线程)开始执行。

 
  
  1. final CountDownLatch cdAnswer = new CountDownLatch(3); 

相当于公布成绩的裁判,每个运动员到达终点时,给裁判一个信号,“我到了(相当于将计数器减1)”,当3个“运动员”(线程)都到达时,裁判才会公布成绩,即

 
  
  1. cdAnswer.await();  

下面的代码才会执行。

总结:CountDownLatch可以实现“一个人”通知“多个人”的效果,也可以实现多个人通知一个人的效果。