参考文章:http://blog.csdn.net/lmc_wy/article/details/7866863 (闭锁CountDownLatch与栅栏CyclicBarrier)
所有线程互相等待,直到大家都到达一个水平线上,大家在继续运行,这个水平线就是栅栏。
栅栏:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点。利用栅栏,可以使线程相互等待,直到所有线程都到达某一点,然后栅栏将打开,所有线程将通过栅栏继续执行。CyclicBarrier支持一个可选的 Runnable
参数,当线程通过栅栏时,runnable对象将被调用。构造函数CyclicBarrier(int parties, Runnable barrierAction)
,当线程在CyclicBarrier对象上调用await()
方法时,栅栏的计数器将增加1,当计数器为parties
时,栅栏将打开。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
final int count = 5;
final CyclicBarrier barrier = new CyclicBarrier(count, new Runnable() {
@Override
public void run() {
System.out.println("大家都跑完了!");
}
});
for (int i = 0; i < count; i++) {
new Thread(new Worker(i, barrier)).start();
}
}
}
class Worker implements Runnable {
final int id;
final CyclicBarrier barrier;
public Worker(final int id, final CyclicBarrier barrier) {
this.id = id;
this.barrier = barrier;
}
@Override
public void run() {
try {
System.out.println(this.id + "starts to run !");
Thread.sleep((long) (Math.random() * 10000));
System.out.println(this.id + "arrived !");
this.barrier.await(); //跑到这个地方等待
System.out.println(this.id+"--end--time:{"+System.currentTimeMillis()+"}");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
运行结果:
0starts to run !
1starts to run !
2starts to run !
3starts to run !
4starts to run !
1arrived !
4arrived !
3arrived !
0arrived !
2arrived !
大家都跑完了!
2--end--time:{1469688224243}
1--end--time:{1469688224243}
3--end--time:{1469688224243}
4--end--time:{1469688224243}
0--end--time:{1469688224243}
再来一个例子,从线程池拿5个线程,这些线程启动后同时去干一件事情,用CyclicBarrier实现
public static void main(String[] args) {
final CyclicBarrier barrier=new CyclicBarrier(5);
ExecutorService service= Executors.newFixedThreadPool(5);
for(int i=0;i<5;i++){
service.execute(new Runnable() {
@Override
public void run() {
try {
long wait=(long)(Math.random()*10000);
System.out.println(wait);
Thread.sleep(wait); //模拟线程启动耗时
barrier.await(); //等待大家都启动
System.out.println("start time :"+System.currentTimeMillis()); //大家同时开始干活
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}