区别
Javadoc 原文:
CountDownLatch: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
CyclicBarrier : A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
可译为:
CountDownLatch : 一个或多个线程等待一批线程完成某个操作之后才能继续执行。
CyclicBarrier : 一批线程之间相互等待各自达到共同的栅栏点,任何一个线程到达之前,所有的线程必须等待。
对比两段解释我们可以看出,对于CountDownLatch来说,重点是那个“一个线程”,只有它在等待,而另外那批线程在做完某个操作之后可以停止阻塞继续执行其它任务。而CyclicBarrier则一批线程之间互相的阻塞,任何一个线程未完成(栅栏点之前的)操作,所有的线程都必须等待。
CountDownLatch 实际应用中多用于计数器,线程完成一个就记一个,就像报数一样,只不过是递减的。
CyclicBarrier 望其名知其义,它更像是一道屏障,只有所有线程到齐之后才能解除这道屏障。
下面举例说明。
CountDownLatch 代码示例
import java.util.concurrent.CountDownLatch;
/**
* @author: xiebochang
* @Title: TsCountDownLatch
* @date: 2020/8/12
*/
public class TsCountDownLatch {
public static void main (String[] args) throws InterruptedException {
int threadCount = 5;
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "作业完成");
latch.countDown();
// 不被阻塞
System.out.println(Thread.currentThread().getName() + "跑去喝了杯水");
}).start();
}
latch.await();
System.out.println("大家作业都完成了,可以一起愉快开黑了");
}
}
执行结果:
Thread-0作业完成
Thread-4作业完成
Thread-4跑去喝了杯水
Thread-3作业完成
Thread-3跑去喝了杯水
Thread-1作业完成
Thread-1跑去喝了杯水
Thread-2作业完成
Thread-0跑去喝了杯水
大家作业都完成了,可以一起愉快开黑了
Thread-2跑去喝了杯水
从执行结果可以发现,每个线程调用countDown方法后并未被阻塞。因此可以理解为调用countDown方法只是告知一下主线程(也可认为是await方法的执行线程)已经完成任务,至于线程自己是否要去做其他的事情则不会受制于该方法。而在所有线程都告知已完成任务后await方法结束阻塞,继续执行其他任务。注意:实际应用场景CountDownLatch构造方法参数不一定等同于线程数,该参数决定了可以调用多少次countDown方法(每次调用该方法内部count值则减1,在count值为0时await方法便不再阻塞),具体值视应用场景而定。
CyclicBarrier代码示例
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @author: xiebochang
* @Title: TsCyclicBarrier
* @date: 2020/8/12
*/
public class TsCyclicBarrier {
public static void main (String[] args) throws InterruptedException {
System.out.println("选手准备入场");
CyclicBarrier barrier = new CyclicBarrier(5, () -> System.out.println("所有选手入场就位完毕,裁判宣布开始赛跑!"));
for (int i= 0; i < 5; i++) {
new Thread(new workerTask(barrier)).start();
}
}
static class workerTask implements Runnable {
private CyclicBarrier barrier;
public workerTask(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run () {
try {
System.out.println(Thread.currentThread().getName() + "选手已经入场");
barrier.await();
System.out.println(Thread.currentThread().getName() + "选手到达终点!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
执行结果:
选手准备入场
Thread-0选手已经入场
Thread-1选手已经入场
Thread-2选手已经入场
Thread-3选手已经入场
Thread-4选手已经入场
所有选手入场就位完毕,开始赛跑!
Thread-4选手到达终点!
Thread-0选手到达终点!
Thread-2选手到达终点!
Thread-1选手到达终点!
Thread-3选手到达终点!
示例中,裁判开始赛跑的这道指令就像是一道屏障,只要存在选手未入场准备好(线程未达到共同的栅栏点)都会被这道屏障给阻塞,直到所有选手入场准备就绪,屏障则会打开(发起开跑指令,线程停止阻塞),各个选手(线程)开始进行自己的赛跑角逐。
网友评论