一, CyclicBarrier栅栏简介
- 栅栏(Barrier)类似闭锁,他能阻塞一组线程直到某个事件发生.栅栏与闭锁的关键区别在于,所有线程必须同时到达栅栏位置,才能继续执行. 闭锁用于等待事件,而栅栏用于等待其他线程.
- 当所有线程都到达了栅栏位置,那么栅栏将打开,此时所有线程都会被释放,栅栏可以reset以便于下一次复用
- 如果await的调用超时,或者await阻塞的线程被打断,那么栅栏就被认为是打破了,所有阻塞的await调用都将终止并抛出BrokenBarrierException.如果成功地通过栅栏,那么await将为每个线程返回一个唯一的到达索引号.
- CyclicBarrier 的构造函数public CyclicBarrier(int parties,Runnable barrierAction)可以传递一个Runnable对象,当成功通过栅栏时会被执行,且由最后一个进入 barrier 的线程执行。
二, CyclicBarrier示例
public class Test {
private static final int N = 10;
public static void main(String[] args) throws InterruptedException {
CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() {
@Override
public void run() {
//所有线程都到达才会执行,且由最后一个到达的线程执行
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 所有的任务都已经到达栅栏位置,栅栏打开了 "+System.currentTimeMillis() );
}
});
test(barrier,N);
test(barrier,N);
}
private static void test(CyclicBarrier barrier,int nThread) throws InterruptedException{
for(int i=0; i< nThread-1; i++){
CyclicBarrierThread t = new CyclicBarrierThread(barrier);
t.start();
}
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 所有子任务执行完毕 "+System.currentTimeMillis());
System.out.println("******************************************");
//重置以便于复用
barrier.reset();
}
}
class CyclicBarrierThread extends Thread {
CyclicBarrier barrier;
CyclicBarrierThread(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
try {
barrier.await();
System.out.println(Thread.currentThread().getName() + " 执行了 "+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
参考:
<<java编发编程实战>>