`

实战Concurrent(5)

阅读更多

来自http://www.iteye.com/topic/363625

 

5、CountDownLatch

CountDownLatch是一个一次性的同步辅助工具,允许一个或多个线程一直等待,直到计数器值变为0。它有一个构造方法,设定计数器初始值,即在await()结束等待前需要调用多少次countDown()方法。CountDownLatch的计数器不能重置,所以说它是“一次性”的,如果需要重置计数器,可以使用CyclicBarrier。在运行环境检查的主类中,使用了CountDownLatch来等待所有验证结束,在各个并发验证的线程完成任务结束前都会调用countDown(),因为有3个并发的验证,所以将计数器设置为3。

 

最后将所有这些类整合起来,运行环境检查的主类如下。它会创建线程池服务和验证服务,先做一次验证(相当于是对系统做次初始化),随后并发3个验证请求。系统运行完毕会显示实际执行的节点验证次数和执行时间。如果是顺序执行,验证次数应该是13*4=52,但实际的验证次数会少于这个数字(我这里最近一次执行了33次验证),因为如果同时有两个线程要验证同一节点时只会做一次验证。关于时间,如果是顺序执行,52次验证每次等待500ms,那么验证所耗费的时间应该是26000ms,使用了多线程后的实际耗时远小于该数字(最近一次执行耗时4031ms)。

Java代码 
  1. package  service.mock;  
  2.   
  3. import  java.util.ArrayList;  
  4. import  java.util.List;  
  5. import  java.util.concurrent.CountDownLatch;  
  6.   
  7. import  service.Node;  
  8. import  service.ThreadPoolService;  
  9. import  service.ValidationService;  
  10.   
  11. /**  
  12.  * 模拟执行这个环境的验证  
  13.  *   
  14.  * @author DigitalSonic  
  15.  */   
  16. public   class  ValidationStarter  implements  Runnable {  
  17.     private  List<String>      entries;  
  18.     private  ValidationService validationService;  
  19.     private  CountDownLatch    signal;  
  20.   
  21.     public  ValidationStarter(List<String> entries, ValidationService validationService,  
  22.             CountDownLatch signal) {  
  23.         this .entries = entries;  
  24.         this .validationService = validationService;  
  25.         this .signal = signal;  
  26.     }  
  27.   
  28.     /**  
  29.      * 线程池大小为10,初始化执行一次,随后并发三个验证  
  30.      */   
  31.     public   static   void  main(String[] args) {  
  32.         ThreadPoolService threadPoolService = new  ThreadPoolService( 10 );  
  33.         ValidationService validationService = new  ValidationService(threadPoolService);  
  34.         List<String> entries = new  ArrayList<String>();  
  35.         CountDownLatch signal = new  CountDownLatch( 3 );  
  36.         long  start;  
  37.         long  stop;  
  38.   
  39.         for  (Node node : MockNodeValidator.ENTRIES) {  
  40.             entries.add(node.getWsdl());  
  41.         }  
  42.   
  43.         start = System.currentTimeMillis();  
  44.   
  45.         validationService.validate(entries);  
  46.         threadPoolService.execute(new  ValidationStarter(entries, validationService, signal));  
  47.         threadPoolService.execute(new  ValidationStarter(entries, validationService, signal));  
  48.         threadPoolService.execute(new  ValidationStarter(entries, validationService, signal));  
  49.   
  50.         try  {  
  51.             signal.await();  
  52.         } catch  (InterruptedException e) {  
  53.             e.printStackTrace();  
  54.         }  
  55.   
  56.         stop = System.currentTimeMillis();  
  57.         threadPoolService.destoryExecutorService(1000 );  
  58.         System.out.println("实际执行验证次数: "  + MockNodeValidator.getCount());  
  59.         System.out.println("实际执行时间: "  + (stop - start) +  "ms" );  
  60.     }  
  61.   
  62.     @Override   
  63.     public   void  run() {  
  64.         validationService.validate(entries);  
  65.         signal.countDown();  
  66.     }  
  67.   
  68. }  
   

=================================我是分割线==============================

 

本文没有覆盖java.util.concurrent中的所有内容,只是挑选一些比较常用的东西,想要获得更多详细信息请阅读JavaDoc。自打有了“轮子”理论,重复造大轮子的情况的确少了,但还是有人会做些小轮子,例如编写多线程程序时用到的小工具(线程池、锁等等),如果可以,请让自己再“懒惰”一点吧~

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics