package cn.cyc.n1;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
public class S1 {
private static CyclicBarrier c=new CyclicBarrier(3);
public static void main(String[] args) throws InterruptedException {
Task task = new Task(c);
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();t2.start();
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
c.reset();
t1.join();t2.join();
System.out.println("_______________");
Thread t11 = new Thread(task);
Thread t21 = new Thread(task);
Thread t31= new Thread(task);
t11.start();t21.start();t31.start();
}
}
class Task implements Runnable{
private CyclicBarrier c;
public Task(CyclicBarrier c){
this.c=c;
}
public void run() {
String e1=null;
int a=-1;
System.out.println(Thread.currentThread().getName()+" 启动");
try {
a=c.await();
} catch (InterruptedException e) {
e1="InterruptedException";
} catch (BrokenBarrierException e) {
e1="BrokenBarrierException";
}
if(e1!=null){System.out.println(Thread.currentThread().getName()+" 抛出异常,e="+e1);return;}
System.out.println(Thread.currentThread().getName()+" *** 完毕 res="+a);
}
}
输出:
Thread-0 启动
Thread-1 启动
Thread-1 抛出异常,e=BrokenBarrierException
Thread-0 抛出异常,e=BrokenBarrierException
_______________
Thread-2 启动
Thread-3 启动
Thread-4 启动
Thread-4 *** 完毕 res=0
Thread-3 *** 完毕 res=1
Thread-2 *** 完毕 res=2
前面2个线程启动后,获取独占锁,由于线程计数器==1,会进入aqs条件队列等待(释放独占锁,挂起)。调用reset更新珊兰,会获取独占锁,打破珊兰(设置generation的broken状态为true,复位线程计数器,唤醒aqs条件队列节点)更新珊兰释放独占锁。前面2个线程节点被添加到线程等待队列,获取独占锁运行完await,由于珊兰被打破抛出异常BrokenBarrierException。珊兰reset执行了更新珊兰的操作(唤醒aqs条件队列等待节点,复位计数器,更新generation)完成复位,后3个线程可以正常使用珊兰。
分析:
CyclicBarrier(int parties, Runnable barrierAction) 构造器,初始化珊兰打开需要的线程数量,需要的线程数量珊兰计数器,以及打开时,最后到达的一个线程执行的任务,为null时候不执行任务。
private final ReentrantLock lock = new ReentrantLock(); 独占锁
private final Condition trip = lock.newCondition(); 独占锁锁上的条件。
breakBarrier 打破珊兰:设置generation的状态 true,初始化需要的线程数量,唤醒条件队列里被挂起的节点。
nextGeneration 更新珊兰:唤醒所有在条件队列上挂起的节点,初始化珊兰计数器,更generation。
await 等待:获取独占锁 如果珊兰被打破,抛出异常;如果线程被中断,打破珊兰,抛出异常;对需要的线程计数器-1,如果为0 说明所有线程已经到达珊兰位置,珊兰打开,运行构造器传入的任务,如果成功执行,更新珊兰,返回0,如果失败,打破珊兰异常退出;自旋 【如果是定时等待,则调用aqs条件队列定时等待,否则调用aqs条件队列非定时等待,如果被中断抛出异常,如果此时generation没有被更新且珊兰未被打破,则打破珊兰抛出异常,否则线程中断;如果珊兰被打破,抛出异常;如果generation被更新,返回计数器值;如果定时且超时,打破珊兰,抛出超时异常。】最后 释放独占锁。所有等待的线程,会由于某个线程中断 超时 打破珊兰 所有线程到达而结束。
reset 重置珊兰:获取独占锁,打破珊兰(设置generation的broken状态为true,设置珊兰所需线程计数器为初始值,唤醒aqs条件队列等待的节点)。更新珊兰(唤醒aqs条件队列等待的节点,设置珊兰打开所需线程计数器为初始值,更新generation),释放独占锁。如果有线程等待珊兰,立即调用此操作会使得等待的线程抛出异常。