CyclicBarrier 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程(这个很重要,在初始化时要指定线程的数量)的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。
CountDownLatch一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。主要方法 public CountDownLatch(int count); public void countDown(); public void await() throws InterruptedException。构造方法参数指定了计数的次数countDown方法,当前线程调用此方法,则计数减一awaint方法,调用此方法会一直阻塞当前线程,直到计时器的值为0
应用场景
在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择CyclicBarrier了。
例:用三个线程处理一个二维数组,每个线程处理一行(每个元素值乘二),每处理完一列后等待 再一起处理下一列。
public void test() throws InterruptedException{
CountDownLatch start=new CountDownLatch(1);
CountDownLatch end=new CountDownLatch(3);
CyclicBarrier barrier=new CyclicBarrier(3, new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("run at barrier ");
for(int i=0;i<3;i++){
System.out.println(result[0][i]+result[1][i]+result[2][i]);
}
}});
for(int i=0;i<3;i++){
new Thread(new TestThread(barrier,i,start,end)).start();
}
Thread.sleep(3000);
System.out.println("start ........");
start.countDown();
System.out.println("wait to end ........");
end.await();
System.out.println("end ........");
}
public int[][] data=new int[][]{{1,2,3},{1,2,3},{1,2,3}};
public int[][] result=new int[3][3];
class TestThread implements Runnable{
CyclicBarrier barrier;
int row;
CountDownLatch start;
CountDownLatch end;
public TestThread(CyclicBarrier barrier, int row,CountDownLatch start,
CountDownLatch end) {
super();
this.barrier = barrier;
this.row = row;
this.start=start;
this.end=end;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
System.out.println("wait to start "+Thread.currentThread().getName());
start.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i=0;i<3;i++){
System.out.println("run at thread "+Thread.currentThread().getName()+" row "+i);
result[row][i]=data[row][i]*2;
try {
barrier.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
end.countDown();
}
}
wait to start Thread-0
wait to start Thread-1
wait to start Thread-2
start ........
wait to end ........
run at thread Thread-2 row 0
run at thread Thread-1 row 0
run at thread Thread-0 row 0
run at barrier
6
0
0
run at thread Thread-0 row 1
run at thread Thread-2 row 1
run at thread Thread-1 row 1
run at barrier
6
12
0
run at thread Thread-1 row 2
run at thread Thread-2 row 2
run at thread Thread-0 row 2
run at barrier
6
12
18
end ........
这与join还不一样,join是在所有的线程结束后,父线程才能继续执行,而CyclicBarrier 则是在子线程内部等待,当所有的线程完成相应的操作步骤后,再进行下一步操作。join类似于汇总,而CyclicBarrier 则用于子线程统一步伐。