CyclicBarrier
CyclicBarrier明面上翻译是循环栅栏的意思。差不多是到了指定的人数把栅栏推到,放人出去,出去后栅栏又被扶起来,再来人,满了,推倒之后又被扶起,如此往复。
下面通过两个场景来分析 CyclicBarrier 的具体用法:
- 场景一:现在需要访问数据库、需要访问网络、需要访问文件系统等,必须这些都完成后才可以进行下面的操作。如果串行化处理效率不高,可以先并行处理后再串行化处理。
public class CyclicBarrierExample {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("---访问文件--- ");
cyclicBarrier.await();
System.out.println(" all finish --");
System.out.println("--都完成去干别的事----");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}.start();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
System.out.println("---访问数据库---");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}.start();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("---访问网络---");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}.start();
}
}
- 场景二:模拟班车,人坐满了就出发一班。如此反复。
public class CyclicBarrierExample2 {
public static void main(String[] args) {
//每满20人就发车、注意后面可以增加一个 Runnable 回调
CyclicBarrier cyclicBarrier = new CyclicBarrier(20, new Runnable() {
@Override
public void run() {
System.out.println("---发车---");
}
});
for (int i = 0; i < 100; i++) {
new Thread(() -> {
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
看到这里,有没有觉得 CountDownLatch 和 CyclicBarrier 似乎很像,我们也可以通过 CountDownLatch你来实现一个类似的 CyclicBarrier。
public class CyclicBarrierExample {
static class MyCountDownLatch extends CountDownLatch {
private final Runnable runnable;
//增加一个回调
public MyCountDownLatch(int count, Runnable runnable) {
super(count);
this.runnable = runnable;
}
public void countDown() {
super.countDown();
if (getCount() == 0) {
this.runnable.run();
}
}
}
public static void main(String[] args) {
final MyCountDownLatch myCountDownLatch = new MyCountDownLatch(2, new Runnable() {
@Override
public void run() {
System.out.println("go go go");
}
});
new Thread() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
myCountDownLatch.countDown();
}
}.start();
new Thread() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
myCountDownLatch.countDown();
}
}.start();
}
}
CountDownLatch 和 CyclicBarrier 的区别:
- CountDownLatch 不能循环使用,而 CyclicBarrier 可以循环使用;
- CountDownLatch 工作线程之间互不关心,但是 CyclicBarrier 工作线程必须达到一个共同的点才会往下执行。