CyclicBarrier介绍 (一)
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。
主要方法:
Java代码 复制代码 收藏代码
//设置parties、count及barrierCommand属性。
CyclicBarrier(int):
//当await的数量到达了设定的数量后,首先执行该Runnable对象。
CyclicBarrier(int,Runnable):
//通知barrier已完成线程
await():
//设置parties、count及barrierCommand属性。
CyclicBarrier(int):
//当await的数量到达了设定的数量后,首先执行该Runnable对象。
CyclicBarrier(int,Runnable):
//通知barrier已完成线程
await():
应用场景
在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择CyclicBarrier了。
实例分析
我们需要统计全国的业务数据。其中各省的数据库是独立的,也就是说按省分库。并且统计的数据量很大,统计过程也比较慢。为了提高性能,快速计算。我们采取并发的方式,多个线程同时计算各省数据,最后再汇总统计。在这里CyclicBarrier就非常有用。看代码:
主要类:
Java代码 复制代码 收藏代码
/**
* 各省数据独立,分库存偖。为了提高计算性能,统计时采用每个省开一个线程先计算单省结果,最后汇总。
*
* @author guangbo email:weigbo@163.com
*
*/
public class Total {
// private ConcurrentHashMap result = new ConcurrentHashMap();
public static void main(String[] args) {
TotalService totalService = new TotalServiceImpl();
CyclicBarrier barrier = new CyclicBarrier(5,
new TotalTask(totalService));
// 实际系统是查出所有省编码code的列表,然后循环,每个code生成一个线程。
new BillTask(new BillServiceImpl(), barrier, "北京").start();
new BillTask(new BillServiceImpl(), barrier, "上海").start();
new BillTask(new BillServiceImpl(), barrier, "广西").start();
new BillTask(new BillServiceImpl(), barrier, "四川").start();
new BillTask(new BillServiceImpl(), barrier, "黑龙江").start();
}
}
/**
* 主任务:汇总任务
*/
class TotalTask implements Runnable {
private TotalService totalService;
TotalTask(TotalService totalService) {
this.totalService = totalService;
}
public void run() {
// 读取内存中各省的数据汇总,过程略。
totalService.count();
System.out.println("=======================================");
System.out.println("开始全国汇总");
}
}
/**
* 子任务:计费任务
*/
class BillTask extends Thread {
// 计费服务
private BillService billService;
private CyclicBarrier barrier;
// 代码,按省代码分类,各省数据库独立。
private String code;
BillTask(BillService billService, CyclicBarrier barrier, String code) {
this.billService = billService;
this.barrier = barrier;
this.code = code;
}
public void run() {
System.out.println("开始计算--" + code + "省--数据!");
billService.bill(code);
// 把bill方法结果存入内存,如ConcurrentHashMap,vector等,代码略
System.out.println(code + "省已经计算完成,并通知汇总Service!");
try {
// 通知barrier已经完成
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
结果:
开始计算--北京省--数据!
开始计算--上海省--数据!
北京省已经计算完成,并通知汇总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个已到达都到齐了,继续走啊
分享到:
相关推荐
标题 "http://topkinghat.iteye.com/blog/840706" 提到的博客链接实际上指向了“姜铁”的个人博客文章,而描述中的 "NULL" 暂无具体信息。不过,标签“源码”和“工具”暗示了这篇博客可能涉及到软件开发的源代码...
http://www.iteye.com/topic/699515 主题:Swing是一把刀 http://www.iteye.com/topic/702804 主题:Swing第二刀:枝间新绿一重重 http://www.iteye.com/topic/707540 主题:Swing第二小刀刀:星星之火可以燎原 ...
NULL 博文链接:https://wy649898543.iteye.com/blog/1423655
博文链接:https://jackzhangyunjie.iteye.com/blog/202349
NULL 博文链接:https://zw7534313.iteye.com/blog/426799
NULL 博文链接:https://ownraul.iteye.com/blog/1277047
NULL 博文链接:https://yizhilong28.iteye.com/blog/1161027
博文链接:https://balaschen.iteye.com/blog/82579
博文链接:https://avery-leo.iteye.com/blog/213980
NULL 博文链接:https://zzz299.iteye.com/blog/691049
NULL 博文链接:https://modun.iteye.com/blog/1595857
博文链接:https://wdfan.iteye.com/blog/197543
NULL 博文链接:https://timewalker.iteye.com/blog/1065615
NULL 博文链接:https://wincheer.iteye.com/blog/774298
NULL 博文链接:https://ajita.iteye.com/blog/1725304
NULL 博文链接:https://qiusenvs.iteye.com/blog/412763
从零开始学Spring Boot,没有积分的可以看博客:http://412887952-qq-com.iteye.com/ 【Spring Boot 系列博客】 0)前言【从零开始学Spring Boot】 : http://412887952-qq-com.iteye.com/blog/2291496 (1...
手机理财1.0.7 博文链接:https://iwinyeah.iteye.com/blog/213328
博文链接:https://hkme.iteye.com/blog/142511