CyclicBarrier介绍

来源:互联网 发布:python openstack开发 编辑:程序博客网 时间:2024/06/05 05:52

原文:http://www.iteye.com/topic/980944

CyclicBarrier介绍 

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。 
主要方法: 
Java代码  收藏代码
  1. //设置parties、count及barrierCommand属性。  
  2. CyclicBarrier(int):  
  3.   
  4. //当await的数量到达了设定的数量后,首先执行该Runnable对象。  total表示每次一起运行的线程总数,当每一轮线程运行结束后,执行afterthread线程。afterthread有点象方法运行结束后的回调函数
  5. CyclicBarrier(int total,Runnable afterthread):  
  6.   
  7. //通知barrier已完成线程  
  8. await():  
  9. 每执行一次awit()方法,brrier会-1,当构造函数参数变为0时,直到所有线程都准备就绪


应用场景 
在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择CyclicBarrier了。 

实例分析 
我们需要统计全国的业务数据。其中各省的数据库是独立的,也就是说按省分库。并且统计的数据量很大,统计过程也比较慢。为了提高性能,快速计算。我们采取并发的方式,多个线程同时计算各省数据,最后再汇总统计。在这里CyclicBarrier就非常有用。看代码: 

主要类: 
Java代码  收藏代码
  1. /** 
  2.  * 各省数据独立,分库存偖。为了提高计算性能,统计时采用每个省开一个线程先计算单省结果,最后汇总。 
  3.  *  
  4.  * @author guangbo email:weigbo@163.com 
  5.  *  
  6.  */  
  7. public class Total {  
  8.   
  9.     // private ConcurrentHashMap result = new ConcurrentHashMap();  
  10.   
  11.     public static void main(String[] args) {  
  12.         TotalService totalService = new TotalServiceImpl();  
  13.         CyclicBarrier barrier = new CyclicBarrier(5,  
  14.                 new TotalTask(totalService));  
  15.   
  16.         // 实际系统是查出所有省编码code的列表,然后循环,每个code生成一个线程。  
  17.         new BillTask(new BillServiceImpl(), barrier, "北京").start();  
  18.         new BillTask(new BillServiceImpl(), barrier, "上海").start();  
  19.         new BillTask(new BillServiceImpl(), barrier, "广西").start();  
  20.         new BillTask(new BillServiceImpl(), barrier, "四川").start();  
  21.         new BillTask(new BillServiceImpl(), barrier, "黑龙江").start();  
  22.   
  23.     }  
  24. }  
  25.   
  26. /** 
  27.  * 主任务:汇总任务 
  28.  */  
  29. class TotalTask implements Runnable {  
  30.     private TotalService totalService;  
  31.   
  32.     TotalTask(TotalService totalService) {  
  33.         this.totalService = totalService;  
  34.     }  
  35.   
  36.     public void run() {  
  37.         // 读取内存中各省的数据汇总,过程略。  
  38.         totalService.count();  
  39.         System.out.println("=======================================");  
  40.         System.out.println("开始全国汇总");  
  41.     }  
  42. }  
  43.   
  44. /** 
  45.  * 子任务:计费任务 
  46.  */  
  47. class BillTask extends Thread {  
  48.     // 计费服务  
  49.     private BillService billService;  
  50.     private CyclicBarrier barrier;  
  51.     // 代码,按省代码分类,各省数据库独立。  
  52.     private String code;  
  53.   
  54.     BillTask(BillService billService, CyclicBarrier barrier, String code) {  
  55.         this.billService = billService;  
  56.         this.barrier = barrier;  
  57.         this.code = code;  
  58.     }  
  59.   
  60.     public void run() {  
  61.         System.out.println("开始计算--" + code + "省--数据!");  
  62.         billService.bill(code);  
  63.         // 把bill方法结果存入内存,如ConcurrentHashMap,vector等,代码略  
  64.         System.out.println(code + "省已经计算完成,并通知汇总Service!");  
  65.         try {  
  66.             // 通知barrier已经完成  
  67.             barrier.await();  
  68.         } catch (InterruptedException e) {  
  69.             e.printStackTrace();  
  70.         } catch (BrokenBarrierException e) {  
  71.             e.printStackTrace();  
  72.         }  
  73.     }  
  74.   
  75. }  


结果: 
开始计算--北京省--数据! 
开始计算--上海省--数据! 
北京省已经计算完成,并通知汇总Service! 
开始计算--四川省--数据! 
四川省已经计算完成,并通知汇总Service! 
上海省已经计算完成,并通知汇总Service! 
开始计算--广西省--数据! 
广西省已经计算完成,并通知汇总Service! 
开始计算--黑龙江省--数据! 
黑龙江省已经计算完成,并通知汇总Service! 
======================================= 
开始全国汇总 

其它业务类 
Java代码  收藏代码
  1. public interface BillService {  
  2.     /* 各省计费 
  3.      * @param code  省编码 
  4.      */  
  5.     public void bill(String code);  
  6.   
  7. }   
  8. public interface TotalService {  
  9.     /** * 汇总各省数据 */  
  10.     public void count();  
  11.   
  12. }  


作者注:这个程序并没有多次循环利用CyclicBarrier,CountDownLatch比CyclicBarrier更适合这个场景。之所以贴出这段代码,是因为这代码写得简单明了。要深入了解读下think in java第四版的赛马程序更合适,在725页。


0 0
原创粉丝点击