边学习,边记录,每天进步一点点。
1. CyclicBarrier理解
CyclicBarrier字面意思是“可重用的栅栏”,它一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点。
CyclicBarrier 是 ReentrantLock 和 Condition 的组合使用。
先定义CyclicBarrier拦截的线程数量(parties)和剩余线程数量(count),初始状态parties = count,然后启动多个线程,当某个线程执行完之后,就加锁,然后count减1,如果发现count不等于0,把当前线程await挂起,直到最后一个线程执行完,发现count等于0,这个时候他不着急唤醒其他等待的线程,他先执行一个任务,这个任务是提前就定义好的,当这个任务完成了,他再把其他的线程唤醒,这时这一组线程就都执行完了,之后他会重置拦截的线程数量,这也是为什么CyclicBarrier可以重复使用的原因,以上就是CyclicBarrier处理的基本流程。
2. CyclicBarrier主要方法
(1)CyclicBarrier(parties,Runnable barrierAction)
初始化相互等待的线程数量以及屏障线程的构造方法。
屏障线程的运行时机:等待的线程数量=拦截的线程数量parties之后,CyclicBarrier打开屏障之前。
(2)CyclicBarrier(parties)
初始化相互等待的线程数量的构造方法。
(3)getParties()
获取正在CyclicBarrier上等待的线程数量。
(4)await()
在CyclicBarrier上进行阻塞等待,直到发生以下情形之一:
①在CyclicBarrier上等待的线程数量达到parties,则所有线程被释放,继续执行。
②当前线程被中断,则抛出InterruptedException异常,并停止等待,继续执行。
③其他等待的线程被中断,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行。
④其他等待的线程超时,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行。
⑤其他线程调用CyclicBarrier.reset()方法,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行。
(5)isBroken()
获取是否破损标志位broken的值,此值有以下几种情况:
①CyclicBarrier初始化时,broken=false,表示屏障未破损。
②如果正在等待的线程被中断,则broken=true,表示屏障破损。
③如果正在等待的线程超时,则broken=true,表示屏障破损。
④如果有线程调用CyclicBarrier.reset()方法,则broken=false,表示屏障回到未破损状态。
(6)reset()
使得CyclicBarrier回归初始状态,直观来看它做了两件事:
如果有正在等待的线程,则会抛出BrokenBarrierException异常,且这些线程停止等待,继续执行。
将是否破损标志位broken置为false。
3. CyclicBarrier和CountDownLatch区别
CyclicBarrier的计数器由自己控制,而CountDownLatch的计数器则由使用者来控制,在CyclicBarrier中线程调用await方法不仅会将自己阻塞还会将计数器减1,而在CountDownLatch中线程调用await方法只是将自己阻塞而不会减少计数器的值。
CountDownLatch只能拦截一轮,而CyclicBarrier可以实现循环拦截。
一般来说用CyclicBarrier可以实现CountDownLatch的功能,而反之则不能,例如上面的赛马程序就只能使用CyclicBarrier来实现。