栅栏(Barrier)
通过闭锁可以启动一组操作,或者等待一组操作结束。闭锁是一次性对象,一旦进入结束状态就不能被重置。
栅栏类似于闭锁,它能够阻塞一组线程直到某个事件发生。栅栏与闭锁的关键区别在于,所有线程必须同时到达栅栏位置,才能继续执行。 闭锁用于等待事件,栅栏用于等待其他线程。
CyclicBarrier
CyclicBarrier 可以使一定数量的参与方反复的在栅栏处汇集。在迭代算法中非常有用(这类问题通常将一个问题拆分为成一系列相互独立的子问题)当线程到达栅栏时将调用 await() 方法,这个方法将阻塞直到所有的线程都到达栅栏的位置。如果所有的线程都到达栅栏位置,那么栅栏将打开,所有的线程都会被释放,而栅栏将会被重置以便下次使用。如果对 await() 的调用超时,或者 await() 阻塞的线程被中断,那么栅栏就认为是被打破了,所有的线程的 await() 调用都将终止并抛出 BrokenBarrierException。
线程成功的通过栅栏,那么 await() 将为每个线程返回一个唯一的到达索引号,我们可以利用这些索引号来选举产生一个领导线程,并在下次迭代中由该领导线程执行一些特殊的工作。
CyclicBarrier 还可以使你将一个栅栏操作传递给构造函数(一个Runnable),当成功通过栅栏时会在一个子任务线程中执行它(在阻塞线程被释放前是不能执行的)
Exchanger
另一种形式的栅栏是 Exchanger,它是一种两方栅栏,各方在栅栏位置交换数据。
当双方执行不对称操作时,Exchanger 会比较好用。例如,当一个线程向缓冲区写入数据,而另一个线程从缓冲区读取数据。这些线程就可以用 Exchanger 来汇合,并将满的缓冲区与空的缓冲区交换。