CyclicBarrier采用一种屏障的方式来控制线程,让所有线程停在某一点,已到的等最后到才完事。先到的线程将处于阻塞的状态。
http://blog.csdn.net/ya_1249463314/article/details/52822580
package java.util.concurrent;
public class CyclicBarrier
说明:下面所说的线程组是指启动此 barrier 的参与者(所有线程)被叫做线程组。
属性:
/** 定义一个排他锁 */
private final ReentrantLock lock = new ReentrantLock();
/** 创建一个等待队列 */
private final Condition trip = lock.newCondition();
/** 等待线程的数量 */
private final int parties;
/* 当栅栏被释放后执行的线程 */
private final Runnable barrierCommand;
/** 当前的一代线程组 */
private Generation generation = new Generation();
/**
* 在当前一代线程组中等待线程的数量从parties减到0。
* count值是在创建新的一代线程时被重置。
*/
private int count;
内部类:
/**
* 一个栅栏代表了一代线程组,栅栏被重置或者跳闸时,一代线程组发生改变。
* 如果一代线程组被实例化了,那么这个栅栏被打破的标志位为false。
*/
private static class Generation {
boolean broken = false;
}
breakBarrier:
设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程
/**
* 设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程
* 在持有锁的时候,才可以调用该方法。
*/
private void breakBarrier() {
//设置一代线程组对应的栅栏状态为true(意思就是栅栏被破坏了)
generation.broken = true;
//重新设置计数count值
count = parties;
//唤醒所有等待的线程
trip.signalAll();
}
nextGeneration:
/**
* 重新设置下一代线程组
* 当栅栏跳闸时,就是线程都到达屏障时,就更新同步状态,然后唤醒所有等待的线程。
* 但是只能在持有锁时才可以调用该方法。
*/
private void nextGeneration() {
//唤醒所有等待的线程
trip.signalAll();
//重新设置计数count值
count = parties;
//重新创建一代线程组
generation = new Generation();
}
doAwait:
主要用于限时等待和非限时等待
/**
* 等待通用方法
*/
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();
}
//获取一代线程组中等待线程的数量-1
int index = --count;
//如果达到跳闸的条件
if (index == 0) { // tripped
boolean ranAction = false;
try {
//获取跳闸后执行的线程
final Runnable command = barrierCommand;
//如果该线程不为空,那么就执行最后的线程
if (command != null)
command.run();
//将标记位设置为true
ranAction = true;
//重新设置下一代线程组
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// 死循环,除非出现栅栏破坏了、线程中断、超时情况才结束循环
for (;;) {
try {
/* timed时间标志位
* 如果timed为false,那么线程等待队列将一直被挂起,线程一直处于等待状态。
*/
if (!timed)
trip.await();
else if (nanos > 0L)
/**
* 如果时间标志位timed为true
* 如果等待时间大于0L,那么将线程等待队列在指定时间到达前将等待
*/
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
//如果当前这一代线程组对应的栅栏状态未破坏
if (g == generation && ! g.broken) {
//设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程
breakBarrier();
//抛出中断异常
throw ie;
} else {
/* 如果线程没有结束等待甚至根本没有中断,那么这个中断操作将会随后在执行。
*
*/
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();
}
}
/**
* 栅栏构造器
* 输入参数为线程组中的等待线程数、最后执行的线程
*/
public CyclicBarrier(int parties, Runnable barrierAction) {
//如果等待线程数不大于0,那么就抛出非法参数异常
if (parties <= 0) throw new IllegalArgumentException();
//初始化等待线程数
this.parties = parties;
//初始化操作线程数
this.count = parties;
//初始化栅栏破坏后,最后执行的线程
this.barrierCommand = barrierAction;
}
/**
* 栅栏构造器
* 就是没有最后执行的线程的栅栏
*/
public CyclicBarrier(int parties) {
this(parties, null);
}
/**
* 获取启动此 barrier 的参与者数目
*/
public int getParties() {
return parties;
}
/**
* 在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。
*/
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
return dowait(true, unit.toNanos(timeout));
}
/**
* 查看屏障是否处于破坏状态
*/
public boolean isBroken() {
//获取当前的排它锁
final ReentrantLock lock = this.lock;
//获取锁
lock.lock();
try {
//返回当前这一代线程组中的状态
return generation.broken;
} finally {
//释放锁
lock.unlock();
}
}
/**
* 将屏障设置为初始化的状态
*/
public void reset() {
//获取排他锁
final ReentrantLock lock = this.lock;
//获取锁
lock.lock();
try {
//设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程
breakBarrier();
//重新设置下一代线程组
nextGeneration();
} finally {
//释放锁
lock.unlock();
}
}
/**
* 获取当前屏障处等待的线程数
*/
public int getNumberWaiting() {
//获取排他锁
final ReentrantLock lock = this.lock;
//获取锁
lock.lock();
try {
//总等待线程数减去当前剩余没到达的线程数
return parties - count;
} finally {
//释放锁
lock.unlock();
}
}
--------------------------------------------jdk1.7