CyclicBarrier和CountDownLatch介绍

本文介绍了Java并发包中的CyclicBarrier类,一种用于多线程间同步的工具。通过实例演示了如何使用CyclicBarrier来确保一组线程在达到某个公共屏障点前相互等待,适用于需要等待所有子任务完成后再进行下一步操作的场景。

CyclicBarrier介绍 (一)
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。 

 

CyclicBarrier (周期障碍)类可以帮助同步,它允许一组线程等待整个线程组到达公共屏障点。CyclicBarrier 是使用整型变量构造的,其确定组中的线程数。当一个线程到达屏障时(通过调用 CyclicBarrier.await()),它会被阻塞,直到所有线程都到达屏障,然后在该点允许所有线程继续执行。与CountDownLatch不同的是,CyclicBarrier 所有公共线程都到达后,可以继续执行下一个目标点,而CountDownLatch第一次到达指定点后,也就是记数器减制零,就无法再次执行下一目标工作。

 

应用场景
在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择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!
=======================================
开始全国汇总
CyclicBarrier介绍 (二)

张孝祥视频学习笔记:

CyclicBarrier 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在i指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐……

iimport java.util.concurrent.BrokenBarrierException;

import java.util.concurrent.CyclicBarrier;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class CyclicBarrierTest {

 public static void main(String [] args){

  ExecutorService service=Executors.newCachedThreadPool();

  final CyclicBarrier cb= new CyclicBarrier(3);  //三个线程同时到达

  for( int i=0;i<3;i++){        

   Runnable runnable=new Runnable(){

    public void run(){

     try {

      Thread.sleep((long)(Math.random()*10000));

      System. out.println("线程" +Thread.currentThread ().getName()+

        "即将到达集合地点1,当前已有" +(cb.getNumberWaiting()+1)+"个已到达"+

        (cb.getNumberWaiting()==2? "都到齐了,继续走啊" :"正在等候" ));

      try {

       cb.await();

      } catch (BrokenBarrierException e) {

       // TODO Auto-generated catch block

       e.printStackTrace();

      }

      Thread.sleep((long)(Math.random()*10000));

      System. out.println("线程" +Thread.currentThread ().getName()+

        "即将到达集合地点2,当前已有" +(cb.getNumberWaiting()+1)+"个已到达"+

        (cb.getNumberWaiting()==2? "都到齐了,继续走啊" :"正在等候" ));

      try {

       cb.await();

      } catch (BrokenBarrierException e) {

       // TODO Auto-generated catch block

       e.printStackTrace();

      }

      Thread.sleep((long)(Math.random()*10000));

      System.out.println("线程" +Thread.currentThread ().getName()+

        "即将到达集合地点3,当前已有" +(cb.getNumberWaiting()+1)+"个已到达"+

        (cb.getNumberWaiting()==2? "都到齐了,继续走啊" :"正在等候" ));

      try {

       cb.await();

      } catch (BrokenBarrierException e) {

       // TODO Auto-generated catch block

       e.printStackTrace();

      }

     } catch (InterruptedException e) {

      // TODO Auto-generated catch block

      e.printStackTrace();

     }

    }

   };

   service.execute(runnable);

  }

  service.shutdown();

 }

}

运行结果:

线程pool-1-thread-3即将到达集合地点1,当前已有1个已到达正在等候
线程pool-1-thread-2即将到达集合地点1,当前已有2个已到达正在等候
线程pool-1-thread-1即将到达集合地点1,当前已有3个已到达都到齐了,继续走啊
线程pool-1-thread-1即将到达集合地点2,当前已有1个已到达正在等候
线程pool-1-thread-2即将到达集合地点2,当前已有2个已到达正在等候
线程pool-1-thread-3即将到达集合地点2,当前已有3个已到达都到齐了,继续走啊
线程pool-1-thread-2即将到达集合地点3,当前已有1个已到达正在等候
线程pool-1-thread-1即将到达集合地点3,当前已有2个已到达正在等候
线程pool-1-thread-3即将到达集合地点3,当前已有3个已到达都到齐了,继续走啊


特别说明:尊重作者的劳动成果,转载请注明出处哦~~~http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp70
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值