CyclicBarrier:
表示大家彼此等待,集合好后在开始出发,分散活动后又在指定地点集合碰面,这就好比 整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时 出发到公园游玩,在指定地点集合后再同时开始就餐……
package Multithreading;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3);
for (int i = 0; i < 3; i++) {//创建3个线程
Runnable runnable = new Runnable() {
public void run() {
try {
//地点1
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程"
+ Thread.currentThread().getName()
+ "即将到达集合地点1,当前已有"
+ (cb.getNumberWaiting() + 1)
+ "个已经到达,"
+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
: "正在等候"));
cb.await();
//地点2
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程"
+ Thread.currentThread().getName()
+ "即将到达集合地点2,当前已有"
+ (cb.getNumberWaiting() + 1)
+ "个已经到达,"
+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
: "正在等候"));
cb.await();
//地点3
Thread.sleep((long) (Math.random() * 10000));
System.out.println("线程"
+ Thread.currentThread().getName()
+ "即将到达集合地点3,当前已有"
+ (cb.getNumberWaiting() + 1)
+ "个已经到达,"
+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊"
: "正在等候"));
cb.await();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);//在未来某个时间执行给定的命令。
}
service.shutdown();
}
}
示例用法:下面是一个在并行分解设计中使用 barrier 的例子:
class Solver {
final int N;
final float[][] data;
final CyclicBarrier barrier;
class Worker implements Runnable {
int myRow;
Worker(int row) { myRow = row; }
public void run() {
while (!done()) {
processRow(myRow);
try {
barrier.await();
} catch (InterruptedException ex) {
return;
} catch (BrokenBarrierException ex) {
return;
}
}
}
}
public Solver(float[][] matrix) {
data = matrix;
N = matrix.length;
barrier = new CyclicBarrier(N,
new Runnable() {
public void run() {
mergeRows(...);
}
});
for (int i = 0; i < N; ++i)
new Thread(new Worker(i)).start();
waitUntilDone();
}
}
在这个例子中,每个 worker 线程处理矩阵的一行,在处理完所有的行之前,该线程将一直在屏障处等待。处理完所有的行之后,将执行所提供的
Runnable
屏障操作,并合并这些行。如果合并者确定已经找到了一个解决方案,那么
done() 将返回
true,所有的 worker 线程都将终止。
如果屏障操作在执行时不依赖于正挂起的线程,则线程组中的任何线程在获得释放时都能执行该操作。为方便此操作,每次调用 await()
都将返回能到达屏障处的线程的索引。然后,您可以选择哪个线程应该执行屏障操作,例如:
if (barrier.await() == 0) { // log the completion of this iteration }
对于失败的同步尝试,CyclicBarrier 使用了一种要么全部要么全不 (all-or-none) 的破坏模式:如果因为中断、失败或者超时等原因,导致线程过早地离开了屏障点,那么在该屏障点等待的其他所有线程也将通过 BrokenBarrierException
(如果它们几乎同时被中断,则用 InterruptedException
)以反常的方式离开。
内存一致性效果:线程中调用 await()
之前的操作 happen-before 那些是屏障操作的一部份的操作,后者依次 happen-before 紧跟在从另一个线程中对应 await()
成功返回的操作。