本例介绍第三个同步装置:CyclicBarrier,它维护一个计数器,与CountDownLatch不同的是,等待这个CyclicBarrier的线程必须等到计数器到达某个值时,才可以继续。CyclicBarrier就像它名字的意思一样,可看成是个障碍,所有的线程必须到齐后才能一起通过这个障碍。本例实现一个数组相邻元素的加法,一个线程给数组的第一个元素赋值,然后等待其他线程给数组第二个元素赋值,然后将第一个元素和第二个元素相加。
CyclicBarrier?(周期障碍)类可以帮助同步,它允许一组线程等待整个线程组到达公共屏障点。CyclicBarrier 是使用整型变量构造的,其确定组中的线程数。当一个线程到达屏障时(通过调用 CyclicBarrier.await()),它会被阻塞,直到所有线程都到达屏障,然后在该点允许所有线程继续执行。与CountDownLatch不同的是,CyclicBarrier 所有公共线程都到达后,可以继续执行下一个目标点,而CountDownLatch第一次到达指定点后,也就是记数器减制零,就无法再次执行下一目标工作。
构造CyclicBarrier对象时,需要指定计数器的目标值,计数器的初始值为0.还可以在构造方法中带一个Runnable参数,表示当计数器到达目标值时,在等待CyclicBarrier的线程被唤醒之前,指定该Runnable任务。
CyclicBarrier的await方法使当前线程进入等待状态,计数器加1,当计数器到达目标值时,当前线程被唤醒。
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
/** */ /**
* CyclicBarrier类似于CountDownLatch也是个计数器,
* 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,
* 当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。
* CyclicBarrier就象它名字的意思一样,可看成是个障碍,
* 所有的线程必须到齐后才能一起通过这个障碍。
* CyclicBarrier初始时还可带一个Runnable的参数,
* 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
*/
public class CyclicBarrierTest {
public static class ComponentThread implements Runnable {
CyclicBarrier barrier;// 计数器
int ID; // 组件标识
int[] array; // 数据数组
// 构造方法
public ComponentThread(CyclicBarrier barrier, int[] array, int ID) {
this.barrier = barrier;
this.ID = ID;
this.array = array;
}
public void run() {
try {
array[ID] = new Random().nextInt(100);
System.out.println("Component " + ID + " generates: " + array[ID]);
// 在这里等待Barrier处
System.out.println("Component " + ID + " sleep");
barrier.await();
System.out.println("Component " + ID + " awaked");
// 计算数据数组中的当前值和后续值
int result = array[ID] + array[ID + 1];
System.out.println("Component " + ID + " result: " + result);
} catch (Exception ex) {
}
}
}
/** *//**
* 测试CyclicBarrier的用法
*/
public static void testCyclicBarrier() {
final int[] array = new int[3];
CyclicBarrier barrier = new CyclicBarrier(2, new Runnable() {
// 在所有线程都到达Barrier时执行
public void run() {
System.out.println("testCyclicBarrier run");
array[2] = array[0] + array[1];
}
});
// 启动线程
new Thread(new ComponentThread(barrier, array, 0)).start();
new Thread(new ComponentThread(barrier, array, 1)).start();
}
public static void main(String[] args) {
CyclicBarrierTest.testCyclicBarrier();
}
}