(21)CyclicBarrier
允许一组线程互相等待,直到某个公共屏障点 (common barrier point)。固定大小线程程序中,线程必须不时地互相等待。barrier释放等待线程后可重用。通俗讲:线程到达屏障被阻塞,最后一个线程到达屏障,屏障才开门,被屏障拦截线程才继续干活。
一、实现分析
内部用重入锁ReentrantLock和Condition。两个构造函数:
CyclicBarrier(int parties):建新CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,启动 barrier 时不执行预定义操作。
CyclicBarrier(int parties, Runnable barrierAction) :建新CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,启动 barrier 时执行给定屏障操作,该操作由最后一个进入 barrier 的线程执行。
parties:拦截线程数量。 barrierAction 为CyclicBarrier接收Runnable命令,在线程到达屏障时,优先执行barrierAction ,处理复杂场景。
最重要的await()方法,参与者都已在此 barrier 上调用 await 前,一直等待。
不是到达最后一个线程,一直等待状态,除非
1)最后一个线程到达,即index == 0
2)超时等待
3)其他线程中断当前线程
4)其他线程中断另一个等待线程
5)其他线程等待barrier超时
6)其他线程在barrier调用reset()将屏障重置为初始状态。
上面源码中,注意Generation 对象,抛出BrokenBarrierException异常场景:
线程等待;其他线程调reset();调用barrier原本被损坏,将barrier置于损坏状态。Generation描述CyclicBarrier更显换代。
CyclicBarrier中,同一批线程属于同一代。有parties个线程到达barrier,generation就会被更新换代。broken标识该当前CyclicBarrier是否中断状态。
signalAll将唤醒全部等待线程。 所有线程都到达barrier(index == 0),通过nextGeneration()更新换地,三件事:唤醒所有线程,重置count,generation
也提供await(long timeout, TimeUnit unit) 做超时控制,内部用doawait()
二、应用场景
与多线程结果合并,多线程计算数据,最后合并计算结果。统计多个Excel中数据,等总结果。多线程处理每个Excel,barrierAction计算线程计算结果,得到所有Excel总和。