Cyclic是周期的意思,Barrier是关卡的意思。CyclicBarrier不仅有CountDownLatch的功能,还可以实现屏障等待,即阶段性同步。因此适用于,需要循环地实现线程一起做任务的目标。
CyclicBarrier允许一组线程相互等待,直到到达某个公共屏障点,如果某些进程需要实时地相互等待,就可以使用CyclicBarrier。CyclicBarrier的重点在于,任何一个线程没有完成任务,其他所有的线程都必须等待,即,同类相互等待。
CyclicBarrier的计数是加法操作。
new CyclicBarrier(5, new
Runnable(){})设置最大为5个同行者,当线程个数等于同行者数目时,即只有5个线程,则5个线程都执行了cbRef的await()方法后,才会走到run()方法内,然后每个方法再各自继续执行。否则这些线程彼此相互等待,一直阻塞。
当线程个数大于partier(同行者)数量时,凑齐同行者数量个线程的await后,就会走到run方法内,凑齐的方法也会各自继续执行。之后再次凑齐,会再执行一遍run方法,各自继续执行。从而实现分批进行。当循环执行时,到达屏障点一同执行的线程组合是可能是随机的。
CyclicBarrier具有屏障重置性。当凑齐同行者数目后,使用getNumberWaiting()方法可以看到,等待数量变为0.再来一个同行者,等待数目就会变成n-1。
isBroken()方法查询此屏障是否处于损坏状态。如果其中一个进程因为出现异常而中断,不会影响其他进程的执行和等待,但是,如果用Thread的interrupt()方法进行中断,则所有的线程都会抛出BrokenBarrierException异常。也就是说,CyclicBarrier类对现成的中断处理,会使用全有、或者全无的破坏模型。即,有一个线程因为超时或中断提前离开了屏障点,其他所有在屏障点等待的线程也会抛出异常并离开屏障点。
await(long timeout,
TimeUnit unit)如果在指定时间内达到parties的数量则继续运行,否则抛出超时异常。
getParties()屏障对象的parties个数。
getNumberWaiting()在屏障处等待的线程个数。
reset()重置屏障。屏障被重置后,如果有线程在等待parties,会出现Broken异常。
示例代码https://github.com/whitefancy/OJproblems/tree/master/javaconcurrent/cyclicbarrier
参考文档
《Java并发编程
核心方法与框架》(高洪岩)