1、栅栏的作用就是设定一个阈值,当到达的线程数达到阈值的时候,此时就会放开栅栏,之后执行下一轮循环
2、栅栏除了设定阈值,还可以设定打开栅栏后执行的新任务
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;//栅栏开启所需线程数
this.count = parties;//剩余未到达的线程
this.barrierCommand = barrierAction;//新任务
}
3、CyclicBarrier与CountDownLatch完成了一样的功能,但是CyclicBarrier可以通过reset来重置,重新恢复栅栏功能。
实例
package chapter8;
import java.util.ArrayList;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
class Prepare implements Runnable {
CyclicBarrier cb;
public Prepare(CyclicBarrier cb) {
this.cb = cb;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "准备完成");
cb.await();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "中断");
} catch (BrokenBarrierException e) {
System.out.println(Thread.currentThread().getName() + "BrokenBarrierException");
// 遇到栅栏损坏,重新来一句,原来到达的线程散伙,但是栅栏重置,当有新线程到达的时候,依旧可以开始
cb.reset();
}
}
}
public class CyclicBarrierDemo {
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("运动员到齐,开始跑");
}
});
ArrayList<Thread> list = new ArrayList<>();
for (int i = 0; i < 9; i++) {
Thread thread = new Thread(new Prepare(cyclicBarrier), "[第" + i + "运动员]");
list.add(thread);
thread.sleep(1000);
thread.start();
if (i == 3) {
thread.interrupt();
}
}
Thread.sleep(1000);
System.out.println("栅栏损坏" + cyclicBarrier.isBroken());
}
}
1、可能运行结果:
[第0运动员]准备完成
[第1运动员]准备完成
[第2运动员]准备完成
[第3运动员]准备完成
[第1运动员]BrokenBarrierException
[第2运动员]BrokenBarrierException
[第0运动员]BrokenBarrierException
[第3运动员]中断
[第4运动员]准备完成
[第5运动员]准备完成
[第6运动员]准备完成
[第7运动员]准备完成
[第8运动员]准备完成
运动员到齐,开始跑
栅栏损坏false
2、结果分析:
(1)首先0.1.2.3运动员准备,之后3运动员中断,此时会导致0.1.2运动员抛出BrokenBarrierException错误
(2)在抛出BrokenBarrierException错误后reset栅栏,相当于栅栏重新起作用
(3)原来的0.1.2.3.4运动员散伙,之后等待新的运动员入场后才能开始比赛
(4)运动员5.6.7.8入场准备完成,开始比赛
(5)判断栅栏状态,没有被损坏,是因为损坏栅栏之后reset了