CyclicBarrier 、CountDownLatch


      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 则用于子线程统一步伐。

 

你可能感兴趣的:(CyclicBarrier 、CountDownLatch)