CyclicBarrier概念
这个是在并发时,要求所有线程都到达屏障,最后统一释放
那他有啥作用那也就是
让一组线程相互等待,等待所有的线程都到达公共屏障点
这个屏障点Barrier
CyclicBarrier类中的方法和参数
参数详解
public class CyclicBarrier {
/** The lock for guarding barrier entry */
//lock锁,针对于屏障来服务
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
// 用于声明等待的队列
private final Condition trip = lock.newCondition();
/** The number of parties */
//线程数量
private final int parties;
/* The command to run when tripped */
// 所有线程到达后,最后一个线程要做的事情
private final Runnable barrierCommand;
/** The current generation */
//当前代,每次循环都是一代
private Generation generation = new Generation();
/**
* Number of parties still waiting. Counts down from parties to 0
* on each generation. It is reset to parties on each new
* generation or when broken.
*/
//等待的线程数量
private int count;
...
}
CyclicBarrier的构造函数
/**
* Creates a new {@code CyclicBarrier} that will trip when the
* given number of parties (threads) are waiting upon it, and which
* will execute the given barrier action when the barrier is tripped,
* performed by the last thread entering the barrier.
*
* @param parties the number of threads that must invoke {@link #await}
* before the barrier is tripped
* @param barrierAction the command to execute when the barrier is
* tripped, or {@code null} if there is no action
* @throws IllegalArgumentException if {@code parties} is less than 1
* 声明有多少个线程执行,和线程到达后,最后一个线程干什么
*/
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
/**
* Creates a new {@code CyclicBarrier} that will trip when the
* given number of parties (threads) are waiting upon it, and
* does not perform a predefined action when the barrier is tripped.
*
* @param parties the number of threads that must invoke {@link #await}
* before the barrier is tripped
* @throws IllegalArgumentException if {@code parties} is less than 1
* 只声明有多少个线程执行,执行后,什么也不干
*/
public CyclicBarrier(int parties) {
this(parties, null);
}
CyclicBarrier等待执行
让parties个线程等待执行
直到parties个线程到达barrier” 或 “当前线程被中断” 或 “超时”这3者之一发生,当前线程就会继续执行
/**
* Waits until all {@linkplain #getParties parties} have invoked
* {@code await} on this barrier.
*
* <p>If the current thread is not the last to arrive then it is
* disabled for thread scheduling purposes and lies dormant until
* one of the following things happens:
* <ul>
* <li>The last thread arrives; or
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* one of the other waiting threads; or
* <li>Some other thread times out while waiting for barrier; or
* <li>Some other thread invokes {@link #reset} on this barrier.
* </ul>
*
* <p>If the current thread:
* <ul>
* <li>has its interrupted status set on entry to this method; or
* <li>is {@linkplain Thread#interrupt interrupted} while waiting
* </ul>
* then {@link InterruptedException} is thrown and the current thread's
* interrupted status is cleared.
*
* <p>If the barrier is {@link #reset} while any thread is waiting,
* or if the barrier {@linkplain #isBroken is broken} when
* {@code await} is invoked, or while any thread is waiting, then
* {@link BrokenBarrierException} is thrown.
*
* <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
* then all other waiting threads will throw
* {@link BrokenBarrierException} and the barrier is placed in the broken
* state.
*
* <p>If the current thread is the last thread to arrive, and a
* non-null barrier action was supplied in the constructor, then the
* current thread runs the action before allowing the other threads to
* continue.
* If an exception occurs during the barrier action then that exception
* will be propagated in the current thread and the barrier is placed in
* the broken state.
*
* @return the arrival index of the current thread, where index
* {@code getParties() - 1} indicates the first
* to arrive and zero indicates the last to arrive
* @throws InterruptedException if the current thread was interrupted
* while waiting
* @throws BrokenBarrierException if <em>another</em> thread was
* interrupted or timed out while the current thread was
* waiting, or the barrier was reset, or the barrier was
* broken when {@code await} was called, or the barrier
* action (if present) failed due to an exception
*/
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
首先调用dowait()方法,这个方法在源码中页写到是barrier的核心方法
这个方法声明了一个可重入锁,通过这个锁来实现Barrier
/**
* Main barrier code, covering the various policies.
*/
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
// 首先获取这个独占锁
lock.lock();
try {
// 保存当前的generation
final Generation g = generation;
//如果broken为true,则代表这个栅栏已经被损坏,抛出异常
if (g.broken)
throw new BrokenBarrierException();
//判断是否线程中断,如果中断,则利用breakBarrier方法打破栅栏,
// 让所有等待的线程执行
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
//将技术减一
int index = --count;
//判断是否已经有parties个线程到达屏障
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
//判断是否有线程到达后要做的事情,如果有,就立刻执行
if (command != null)
command.run();
ranAction = true;
//唤醒所有线程,更新下一代
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// 当前线程一直阻塞,直到“有parties个线程到达barrier” 或 “当前线程被中断” 或
// “超时”这3者之一发生,
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
// 判断是否是超时等待,如果不是,就调用awaitNanos(nanos)
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();
// 判断是否开启下一代,是的话,返回index值
if (g != generation)
return index;
//如果时间等待超时,则打破栅栏,调用breakBarrier()方法,让所有线程一起执行
//并且抛出一个超时异常
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
//释放这把可重入锁
lock.unlock();
}
}
好像Generation没有具体细说
Generation是CyclicBarrier的一代线程,这是为了CyclicBarrier可以重复使用
/**
* Each use of the barrier is represented as a generation instance.
* The generation changes whenever the barrier is tripped, or
* is reset. There can be many generations associated with threads
* using the barrier - due to the non-deterministic way the lock
* may be allocated to waiting threads - but only one of these
* can be active at a time (the one to which {@code count} applies)
* and all the rest are either broken or tripped.
* There need not be an active generation if there has been a break
* but no subsequent reset.
*/
private static class Generation {
boolean broken = false;
}
再说一下CyclicBarrier的方法reset()的方法
重新获得这把可重入锁,打破栅栏,开启下一代,重置count
/**
* Resets the barrier to its initial state. If any parties are
* currently waiting at the barrier, they will return with a
* {@link BrokenBarrierException}. Note that resets <em>after</em>
* a breakage has occurred for other reasons can be complicated to
* carry out; threads need to re-synchronize in some other way,
* and choose one to perform the reset. It may be preferable to
* instead create a new barrier for subsequent use.
*/
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
多多练习
public static void main(String[] args){
CyclicBarrier barrier=new CyclicBarrier(2);
for(int i=0;i<2;i++){
Thread thread1=new Thread(new Runnable(){
@Override
public void run() {
// TODO 自动生成的方法存根
try {
System.out.println("我是"+Thread.currentThread().getName()+
"线程");
barrier.await();
System.out.println("我在阻塞完之后执行...");
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
thread1.start();
}
}