栅栏功能是阻塞一组线程直到某个事件的发生,当参与的线程达到栅栏位置的时候,将会调用await()方法,这将会阻塞当前线程直到所有的线程全部到达了栅栏。如果所有的线程都到达了栅栏,那么栅栏便会打开,此时所有的线程都会释放,而栅栏将被重置以便下次使用。
CyclicBarrier有两个构造参数,如下。
CyclicBarrier(int parties)
CyclicBarrier(int parties, Runnable barrierAction)
1.其中parities表示的是参与线程的个数,当前线程在调用await()方法的时候会进行阻塞,调用await()方法,计数器+1.当计数器等于parities的时候,栅栏便会放开。也就是执行到最后一个参与线程,此线程调用await()方法的时候,所有线程同时执行。
2.barrierAction表示的是最后一个线程到达屏障时优先执行的任务。
依旧拿比赛的事来说吧,例子是选手准备,然后释放栅栏,run()方法代码执行完表示运动员到达终点。还有例子就是不管开始,只有所有人都完成比赛,可以庆祝之类的。无非是任务的类Runner类里面的cyclicBarrier.await()位置的问题,选择CyclicBarrier的第二个构造器即可。
public class Runner implements Runnable{
private CyclicBarrier cyclicBarrier;
private int number;
public Runner(CyclicBarrier cyclicBarrier, int number) {
this.cyclicBarrier = cyclicBarrier;
this.number = number;
}
public void run() {
try {
System.out.println(number+"th 就位");
cyclicBarrier.await();
System.out.println(number+"th 到达,耗时"+Math.random()*1000);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
public class Race {
public static void main(String[] args) {
final int count = 6;
CyclicBarrier cyclicBarrier = new CyclicBarrier(count);
for(int i = 1 ; i <= count ;i++){
new Thread(new Runner(cyclicBarrier,i)).start();
}
}
}
2th 就位
5th 就位
3th 就位
4th 就位
6th 就位
1th 就位
2th 到达,耗时896.3213862018172
3th 到达,耗时571.0326287073248
4th 到达,耗时625.9050513357512
6th 到达,耗时300.6048271390146
1th 到达,耗时706.7176368903195
5th 到达,耗时235.70225351556374
这个例子可以这么理解,CyclicBarrier中参与线程的数量是6,每当线程有调用barrier.await(),barrier中计数器便会+1,并且当前线程阻塞在barrier.await()这行代码处,当第6个线程调用barrier.await()方法的时候,计数器等于6,此时栅栏便会打开。所有线程中barrier.await()后面的代码便会得到执行。CyclicBarrier(int parties),参与线程的数量是parties,但调用barrier.await()的线程小于parties,即栅栏计数器小于parties,那么所有线程会一直等待下去,得不到执行。
CyclicBarrier有Runnable参数的构造器CyclicBarrier(int parties, Runnable barrierAction),线程通过栅栏时,Runnable对象会被优先执行,然后所有线程barrier.await()后面的代码得到执行。
例如:100米的比赛,所有参赛选手都到终点情况下,比赛结束,否则比赛还在进行中。
public class Runner implements Runnable{
private CyclicBarrier cyclicBarrier;
private int number;
public Runner(CyclicBarrier cyclicBarrier, int number) {
this.cyclicBarrier = cyclicBarrier;
this.number = number;
}
public void run() {
try {
System.out.println(number+"th 开跑!");
Thread.sleep(1000);
System.out.println(number+"th 到达!");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
public class Race {
public static void main(String[] args) {
final int count = 6;
CyclicBarrier cyclicBarrier = new CyclicBarrier(count,new Runnable(){
public void run(){
System.out.println("所有人到达终点,该比赛结束了");
}
});
for(int i = 1 ; i <= count ;i++){
new Thread(new Runner(cyclicBarrier,i)).start();
}
}
}
1th 起跑!
3th 起跑!
5th 起跑!
2th 起跑!
4th 起跑!
6th 起跑!
1th 到达!
5th 到达!
3th 到达!
6th 到达!
4th 到达!
2th 到达!
该比赛结束了
第二个例子将cyclicBarrier.await()方法放在Runner的最后,相当于是最后一个线程执行到这里的时候,此时栅栏释放。所有的线程继续执行。
思想引入自《Java并发编程实战》。