CyclicBarrier的使用和实现原理
它可以实现让一组线程等待至某个状态之后再全部同时执行。
CountDownLatch 在于一定数量的线程执行完毕之后,另一个线程才能开始执行
CyclicBarrier 在于凑齐一定数量的线程,让他们一起执行
CyclicBarrier 还有不同于 CountDownLatch的是,它可以循环使用
public class TestCyclicBarrier {
static {
BasicConfigurator.configure();
}
/**
* 日志
*/
private static Log LOGGER = LogFactory.getLog(TestCyclicBarrier.class);
public static void main(String[] args) throws Throwable {
// 同步计数器的技术周期为3
final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
// 启动子线程,处理“其他”业务
for(int index = 0 ; index < 5 ; index++) {
Thread childThread = new Thread() {
@Override
public void run() {
// 可获得设置的屏障数值
// int parties = cyclicBarrier.getParties();
// 可获取当前已经进入等待状态的任务数量
// int numberWaiting = cyclicBarrier.getNumberWaiting();
TestCyclicBarrier.LOGGER.info("本线程已准备好处理业务......");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
TestCyclicBarrier.LOGGER.error(e.getMessage() , e);
}
TestCyclicBarrier.LOGGER.info("开始处理业务......");
}
};
childThread.start();
}
}
}
转自https://blog.csdn.net/u010963948/article/details/79045329
实现原理:
依赖于 ReenterLock 和Condition
1、状态参数:
private static class Generation {
boolean broken = false;
}
//锁
private final ReentrantLock lock = new ReentrantLock();
//放置阻塞的线程
private final Condition trip = lock.newCondition();
//阻塞的总量
private final int parties;
//当前已经阻塞的数量
private int count;
2、await方法
一个线程中执行CyclicBarrier.await()方法后,
1、获取lock的锁
2、获取当前阻塞的线程数量,如果count==parties 转到4
3、count没有到达parties的线程数,trip.await()将当前线程挂起到condition的队列中
4、到达后,trip.singalAll(),全部唤醒执行,同时重置count
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count; //线程数+1
if (index == 0) { // 线程总数到达,可以执行
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();//执行所有线程
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
trip.await();//阻塞当前线程
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
//执行所有阻塞线程
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}