Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7068392
  • 博文数量: 702
  • 博客积分: 10821
  • 博客等级: 上将
  • 技术积分: 12031
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-02 10:41
个人简介

中科院云平台架构师,专注于数字化、智能化,技术方向:云、Linux内核、AI、MES/ERP/CRM/OA、物联网、传感器、大数据、ML、微服务。

文章分类

全部博文(702)

分类: Java

2014-11-28 21:06:48

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

Java代码 
1.//设置parties、count及barrierCommand属性。  
2.CyclicBarrier(int):  
3. 
4.//当await的数量到达了设定的数量后,首先执行该Runnable对象。  
5.CyclicBarrier(int,Runnable):  
6. 
7.//通知barrier已完成线程  
8.await(): 
//设置parties、count及barrierCommand属性。
CyclicBarrier(int):

//当await的数量到达了设定的数量后,首先执行该Runnable对象。
CyclicBarrier(int,Runnable):

//通知barrier已完成线程
await():

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

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

主要类:

Java代码 
/** 
2. * 各省数据独立,分库存偖。为了提高计算性能,统计时采用每个省开一个线程先计算单省结果,最后汇总。 
3. *  
4. * @author
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指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐……

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

 

阅读(4033) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

noobwatches2014-12-02 11:01:52

代码哥不愧是代码哥

http://www.noobwatches.net/%E8%B1%AA%E9%9B%85-c-7.html
http://www.nbbiao.com/biao-nb-5.html