本文翻译自http://tutorials.jenkov.com/java-util-concurrent/cyclicbarrier.html,人工翻译,仅供学习交流。
CyclicBarrier
java.util.concurrent.CyclicBarrier类是一种通过某种算法同步线程的同步机制。换句话说,在任何线程继续执行之前,除非所有的线程都到达屏障,否则所有线程都要等待。下面是示意图:
两个线程通过调用Cyclibarrier的await()方法等待对方。一旦所有的线程都处在CyclicBarriers等待中,所有的线程都将被释放并且可以继续执行。
创建一个CyclicBarrier
当你创建一个CyclicBarrier时,你可以指定在释放所有线程前需要等待多少个线程。下面是个创建一个CyclicBarrier:
CyclicBarrier barrier = new CyclicBarrier(2);
等待一个CyclicBarrier
下面是一个线程如何在CyclicBarrier前进行等待。
barrier.await();
你也可以指定线程等待的超时时间。当超时时间到达,线程也会释放,不会在CyclicBarrier等待所有线程。下面展示如何指定超时时间:
barrier.await(10, TimeUnit.SECONDS);
等待线程将会一直等待直到以下情况发生:
- 最后一个线程到达(调用await()方法)
- 线程被另一个线程打断(另一个线程调用了interrupt()方法)
- 另一个等待线程被打断
- 在CyclicBarrier等待中另一个等待线程超时
- 一些外部线程调用了CyclicBarrier.reset()方法
CyclicBarrier实例
CyclicBarrier支持屏障实例,屏障实例实际是一个当最后一个线程到达就立马执行的Runnable。你可以通过CyclicBarrier的构造函数传入这个屏障实例。
Runnable barrierAction = ... ;
CyclicBarrier barrier = new CyclicBarrier(2, barrierAction);
CyclicBarrier示例
下面是一个代码示例,演示了如何使用CyclicBarrier:
Runnable barrier1Action = new Runnable() {
public void run() {
System.out.println("BarrierAction 1 executed ");
}
};
Runnable barrier2Action = new Runnable() {
public void run() {
System.out.println("BarrierAction 2 executed ");
}
};
CyclicBarrier barrier1 = new CyclicBarrier(2, barrier1Action);
CyclicBarrier barrier2 = new CyclicBarrier(2, barrier2Action);
CyclicBarrierRunnable barrierRunnable1 =
new CyclicBarrierRunnable(barrier1, barrier2);
CyclicBarrierRunnable barrierRunnable2 =
new CyclicBarrierRunnable(barrier1, barrier2);
new Thread(barrierRunnable1).start();
new Thread(barrierRunnable2).start();
以下是CyclicBarrierRunnable类:
public class CyclicBarrierRunnable implements Runnable{
CyclicBarrier barrier1 = null;
CyclicBarrier barrier2 = null;
public CyclicBarrierRunnable(
CyclicBarrier barrier1,
CyclicBarrier barrier2) {
this.barrier1 = barrier1;
this.barrier2 = barrier2;
}
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +
" waiting at barrier 1");
this.barrier1.await();
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +
" waiting at barrier 2");
this.barrier2.await();
System.out.println(Thread.currentThread().getName() +
" done!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
下面是执行上述代码的控制台输出,注意线程写入控制台的顺序可能因执行而异。有时线程0先打印,有时线程1先打印,等等。
Thread-0 waiting at barrier 1
Thread-1 waiting at barrier 1
BarrierAction 1 executed
Thread-1 waiting at barrier 2
Thread-0 waiting at barrier 2
BarrierAction 2 executed
Thread-0 done!
Thread-1 done!