`

CyclicBarrier和CountDownLatch介绍

阅读更多
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个已到达都到齐了,继续走啊

分享到:
评论

相关推荐

    CountDownLatch和CyclicBarrier用法实例大全

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具类,它们用于协调多个线程间的协作。这两个工具都是在`java.util.concurrent`包下,是Java并发库的重要组成部分。 **CountDownLatch** ...

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf

    本文将对CountDownLatch和CyclicBarrier的使用场景和实现进行详细的介绍。 CountDownLatch的应用场景: CountDownLatch是一个非常有用的线程控制工具,它可以使一个线程等待其他线程达到某一目标后进行自己的下...

    Java中的CountDownLatch与CyclicBarrier:深入理解与应用实践

    本文将详细介绍CountDownLatch和CyclicBarrier的工作原理、使用场景以及如何在实际项目中应用它们。 CountDownLatch和CyclicBarrier是Java并发编程中两个非常有用的同步工具,它们在不同的场景下有着各自的优势。...

    CountDownLatch 和 CyclicBarrier 的运用(含AQS详解)

    ### CountDownLatch 和 CyclicBarrier 的运用(含AQS详解) #### CountDownLatch **定义与特点:** CountDownLatch 是 Java 并发包中的一个重要组件,它主要用于解决“一个或多个线程等待其他线程完成任务”的问题。...

    java并发编程中CountDownLatch和CyclicBarrier的使用.pdf

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具,用于协调多个线程之间的交互。它们都属于java.util.concurrent包下的类,为多线程编程提供了强大的支持。 **CountDownLatch** 是一个...

    线程实例(并发库引入到Java标准库 )

    有以下类的实例: ThreadPool ScheduledThread CyclicBarrier BlockingQueue CountDownLatch FutureTask CompletionService Semaphore

    详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别

    在Java并发编程中,CountDownLatch和CyclicBarrier都是用于协调多线程间同步的重要工具,它们可以帮助开发者在特定条件满足时启动或者结束线程的执行。本文将详细探讨这两个类的内部实现机制以及它们在实际应用场景...

    《Java并发编程艺术》高清带目录中文版

    5. **并发工具类**:介绍Future接口,用于获取异步任务的结果,以及CyclicBarrier和CountDownLatch等协调工具,帮助多个线程进行同步。 6. **原子类与并发流**:讲解java.util.concurrent.atomic包下的原子类,它们...

    java多线程资料

    书中还介绍了Java提供的并发工具,如Semaphore、CyclicBarrier、CountDownLatch和Phaser等,以及ExecutorService和ThreadPoolExecutor的使用,这些都是Java 5及更高版本中引入的重要并发框架。 学习这两个资源,你...

    Java并发编程之栅栏(CyclicBarrier)实例介绍

    与闭锁(CountDownLatch)不同,闭锁通常是一次性的,而CyclicBarrier可以重用,即“循环”在每次所有线程都到达屏障点后重新初始化。 1. **CyclicBarrier的基本概念**: - **屏障点**:CyclicBarrier的核心是屏障...

    28 人齐了,一起行动—CyclicBarrier详解.pdf

    CyclicBarrier 是 Java 并发库中的一种同步工具类...在设计多线程应用时,根据具体需求选择合适的同步工具,如 CyclicBarrier、CountDownLatch 或 Semaphores,可以有效地避免竞态条件和死锁,提高系统的并行处理能力。

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解

    Java并发编程:CountDownLatch与CyclicBarrier和Semaphore的实例详解 Java并发编程是Java语言中的一种高级技术,用于处理多线程编程中的同步问题。Java 1.5中引入了几个高效的辅助类,包括CountDownLatch、...

    CountDownLatch练习

    CountDownLatch是Java并发编程中一个重要的同步工具类,它允许一个或多个线程等待其他线程完成操作。...通过阅读和理解提供的代码样例(如`countdownlatch`文件),可以进一步加深对CountDownLatch的理解和应用。

    Java线程面试题Top50[参照].pdf

    * CyclicBarrier 和 CountDownLatch 都可以用来让一组线程等待其它线程 * CountdownLatch 不能重新使用,而 CyclicBarrier 可以重新使用 八、Java 内存模型是什么? * Java 内存模型规定和指引 Java 程序在不同的...

    CountDownLatch、CyclicBarrier、Semaphore.md

    java 高并发应用场景

    Java中的CyclicBarrier类最全讲义

    虽然`CyclicBarrier`和`CountDownLatch`都是Java并发工具包中用于实现线程间协作的工具,但它们之间存在一些关键的区别: - **用途**:`CyclicBarrier`主要用于需要多个线程同时到达一个点的情况,而`...

    Java concurrency之CountDownLatch原理和示例_动力节点Java学院整理

    CountDownLatch是Java并发编程中一个重要的工具类,用于协调多线程间的同步。它由Java并发包`java....在实际编程中,应根据具体需求选择CountDownLatch或CyclicBarrier,以及其他并发工具,以确保程序的正确性和性能。

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用

    在Java并发编程中,CountDownLatch、CyclicBarrier和Semaphore是三种重要的线程协作工具,它们都基于AbstractQueuedSynchronizer(AQS)框架来实现线程间的同步和协调。AQS是一个内置的锁和同步组件,它为构建高级...

Global site tag (gtag.js) - Google Analytics