一、CyclicBarrier(栅栏)
通过闭锁,我们可以启动一组相关的操作、或者等待一组相关的操作结束。闭锁是一次性对象,到达终止状态后将不可用。
CyclicBarrier与闭锁类似,能够延迟一组线程的进度直到到达某个状态。栅栏与闭锁的关键区别在于:所有线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏等待其它线程。
线程在到达栅栏位置时,将调用await方法,这个方法会阻塞直到所有线程都到达栅栏位置。当所有线程都到达栅栏位置时,栅栏被认为打开了,此时所有线程都将被释放,栅栏也将被重置以便下次使用,并且await方法会为每个通过的线程返回一个唯一的索引号;如果一个线程在等待栅栏(调用await方法)时超时或者被中断,就认为栅栏被打破了,此时所有在栅栏上等待的线程都将抛出BrokenBarrierException异常。并且栅栏如果是被打破的状态,调用await方法将不阻塞,而是直接抛出BrokenBarrierException。
CycllicBarrier还可以通过构造函数中传入Runaable barrierAction携带一个任务。当最后一个线程达到栅栏位置,栅栏打开,会首先执行完这个barrierAction,再释放被阻塞的线程。如果barrierAction抛出异常,栅栏也会被打破,所有在栅栏上等待的线程都会抛出BrokenBarrierException异常。所以这个barrierAction需要慎用
CyclicBarrier主要方法:
方法 | 说明 |
---|---|
CyclicBarrier(int parties) | 构造一个新的栅栏,parties为在栅栏上等待的线程数量 |
CyclicBarrier(int parties, Runnable barrierAction) | 构造一个新栅栏,parties为在栅栏上等待的线程数量,barrierAction为栅栏打开时优先执行的任务 |
int await() throws InterruptedException, BrokenBarrierException | 阻塞等待直到有足够数量的线程到达栅栏位置。 |
int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException |
限时阻塞,如果当时间到达栅栏还没有打开,则抛出Timeout异常,并且栅栏将被被打破,被阻塞的其它线程都会抛出BrokenBarrierException异常 |
void reset() | 重置栅栏,如果存在正在等待的线程,这些线程将会抛出BrokenBarrierException。在重置之后可以正常调用await方法 |
int getNumberWaiting() | 返回在栅栏上等待的线程数量 |
boolean isBroken() | 栅栏是否处于打破状态 |