CyclicBarrier
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作很有用。
可能这里大家会比较疑惑CountDownLatch和CyclicBarrier究竟有什么区别??
两者主要用于多线程的并发执行。当一个线程需要等待另外一个或多个线程的执行时,就可以考虑用它俩。
共同点:
-
两者的共同点是都具有await()方法,并且执行此方法会引起线程的阻塞,达到某种条件才能继续执行(这种条件也是两者的不同)。 -
还有一个共同点是其构造方法都接受一个int类型的参数,这个值作为计数用,达到该次数即释放等待的线程。
不同点:
-
CountDownLatch是减计数方式,计数==0时释放所有等待的线程;CyclicBarrier是加计数方式,计数达到构造方法中参数指定的值时释放所有等待的线程。 -
CountDownLatch当计数到0时,计数无法被重置;CyclicBarrier计数达到指定值时,计数置为0重新开始。 -
CountDownLatch每次调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响;CyclicBarrier只有一个await()方法,调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞。
package com.uppower.thread;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5, new TotalTask());
// 实际系统是查出所有省编码code的列表,然后循环,每个code生成一个线程。
new BillTask(barrier, "北京").start();
new BillTask(barrier, "上海").start();
new BillTask(barrier, "广西").start();
new BillTask(barrier, "四川").start();
new BillTask(barrier, "黑龙江").start();
}
static class TotalTask implements Runnable {
public void run() {
System.out.println("=======================================");
System.out.println("开始全国汇总");
try {
//doTotalBill() 读取内存中各省的数据汇总,过程略。
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("全国汇总完毕");
System.out.println("=======================================");
}
}
/**
* 子任务:计费任务
*/
static class BillTask extends Thread {
private CyclicBarrier barrier;
// 代码,按省代码分类,各省数据库独立。
private String code;
BillTask(CyclicBarrier barrier, String code) {
this.barrier = barrier;
this.code = code;
}
public void run() {
System.out.println("开始计算--" + code + "省--数据!");
try {
//doBill()
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// 把bill方法结果存入内存,如ConcurrentHashMap,vector等,代码略
System.out.println(code + "省已经计算完成,并通知汇总Service!");
try {
// 通知barrier已经完成
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(" 全国汇总完毕了--" + code + "省又可以happy了!");
}
}
}
运行输出结果:
开始计算--北京省--数据!
开始计算--广西省--数据!
开始计算--四川省--数据!
开始计算--上海省--数据!
开始计算--黑龙江省--数据!
北京省已经计算完成,并通知汇总Service!
广西省已经计算完成,并通知汇总Service!
黑龙江省已经计算完成,并通知汇总Service!
四川省已经计算完成,并通知汇总Service!
上海省已经计算完成,并通知汇总Service!
=======================================
开始全国汇总
全国汇总完毕
=======================================
全国汇总完毕了--北京省又可以happy了!
全国汇总完毕了--黑龙江省又可以happy了!
全国汇总完毕了--广西省又可以happy了!
全国汇总完毕了--四川省又可以happy了!
全国汇总完毕了--上海省又可以happy了!