介绍
CyclickBarrier:循环篱笆。
可以给离散的任务添加逻辑层次。
例如:在跑步比赛中,需要所有运动员都到场了。裁判才能进行吹哨比赛。
1.构造方法如下所示
//创建一个CyclicBarrier对象,并指定其parties
CyclicBarrier(int parties)
//指定parties,并且执行其callBack(在所有线程都到达时执行此barrierAction)
CyclicBarrier(int parties, Runnable barrierAction)
parties:当前CyclicBarrier管理的线程的个数
2.public int await()方法
此方法会在当前的线程位置设置屏障,必须等待所有线程到达这个屏障才会统一的向后执行。如下图所示
此方法的返回值是当前线程的到达数量
如果当前线程数量小于parties数量,那么所有的线程都会在屏障处阻塞
代码如下所示
创建一个带有三个parties的CyclicBarrier,也就是当前管理三个线程,await()屏障必须监控三个线程全都到达,否则一直阻塞。
如下代码中:虽然是Random了,但是一直是同时的结束,就是因为await()的特性:兄弟线程间彼此等待。
public class MyDemo {
private static final Random RANDOM = new Random(System.currentTimeMillis());
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
IntStream.rangeClosed(1,3).forEach(i -> {
new Mytask(cyclicBarrier,"thread - "+i).start();
});
}
private static class Mytask extends Thread{
private final CyclicBarrier cyclicBarrier;
private Mytask(CyclicBarrier cyclicBarrier,String name) {
super(name);
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
System.out.println(getName() + " start run task!");
sleepSeconds(5);
cyclicBarrier.await();
System.out.println(getName() + " run task finished!");
}catch (BrokenBarrierException | InterruptedException e){
e.printStackTrace();
}
}
}
private static void sleepSeconds(long seconds){
try {
TimeUnit.SECONDS.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.重复使用之Reset
reset会重置cuclicBarrier。而且reset还会中断那些在await的线程,如下代码所示,下面两个线程会被await住,但是当reset时这两个线程会被中断。BrokenBarrierException
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(4);
IntStream.rangeClosed(0,2).forEach(i -> {
new Thread(()->{
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
});
TimeUnit.SECONDS.sleep(1L);
cyclicBarrier.reset();
}
4.使用CoundownLatch实现一个简单的CyclicBarrier
提供了一个callBack,在所有线程的线程到达屏障后后可以执行这个callBack
private static class MyCyclicBarrier extends CountDownLatch{
private final Runnable barrierAction;
public MyCyclicBarrier(int count,Runnable barrierAction) {
super(count);
this.barrierAction = barrierAction;
}
public void down(){
this.countDown();
if(this.getCount() == 0){
barrierAction.run();
}
}
}