CountDownLatch和CyclicBarrier的区别
从字面上理解,CountDown表示减法计数,Latch表示门闩的意思,计数为0的时候就可以打开门闩了。Cyclic Barrier表示循环的障碍物。两个类都含有这一个意思:对应的线程都完成工作之后再进行下一步动作,也就是大家都准备好之后再进行下一步。然而两者最大的区别是,进行下一步动作的动作实施者是不一样的。这里的“动作实施者”有两种,一种是主线程(即执行main函数),另一种是执行任务的其他线程,后面叫这种线程为“其他线程”,区分于主线程。对于CountDownLatch,当计数为0的时候,下一步的动作实施者是main函数;对于CyclicBarrier,下一步动作实施者是“其他线程。CountDownLatch是一次性的,而 CyclicBarrie可以继续使用。
总结
CountDownLatch:使用state进行计数,不断递减,计数为0的时候,下一步的动作实施者是main函数。CountDownLatch是一次性的
CyclicBarrier:使用parties进行计数,不断递增,计算最大时,下一步动作实施者是“其他线程。CyclicBarrie可以继续使用。
场景举例说明
CountDownLatch:我们模拟了三个玩家,在三个玩家都准备好之后,游戏才能开始。运行结果:
正在等待所有玩家准备好
Thread-0 已经准备好了
Thread-1 已经准备好了
Thread-2 已经准备好了
开始游戏
public class MyCountDownLatch {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(3);
for(int i = 0; i<countDownLatch.getCount();i++) {
Thread thread = new Thread(new Thread1(countDownLatch));
thread.start();
}
try {
System.out.println("正在等待所有玩家准备好");
countDownLatch.await();
System.out.println("开始游戏");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class Thread1 implements Runnable{
private CountDownLatch countDownLatch;
public Thread1(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+" 已经准备好了");
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
CyclicBarrier:我们模拟三个员工和三个障碍物。可以看到所有的员工翻越了第一个障碍物之后才开始翻越第二个的,下面是运行结果:
ok
Thread-1, 通过了第0个障碍物
Thread-0, 通过了第0个障碍物
Thread-2, 通过了第0个障碍物
Thread-2, 通过了第1个障碍物
Thread-1, 通过了第1个障碍物
Thread-0, 通过了第1个障碍物
Thread-0, 通过了第2个障碍物
Thread-2, 通过了第2个障碍物
Thread-1, 通过了第2个障碍物
public class MyCyclicBarrier {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
for (int i = 0; i<cyclicBarrier.getParties(); i++) {
Thread thread = new Thread(new Thread1(cyclicBarrier));
thread.start();
}
System.out.println("ok");
}
static class Thread1 implements Runnable{
private CyclicBarrier cyclicBarrier;
public Thread1(CyclicBarrier cyclicBarrier){
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
for(int i = 0; i < 3; i++) {
try {
System.out.println(Thread.currentThread().getName() + ", 通过了第"+i+"个障碍物");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
}