CountDownLatch和CyclicBarrier都是控制并发而生,都在java.util.concurrent包下。

CountDownLatch

简单称为计数器,适合1个或者多个线程等待其他线程执行完毕后自己开始执行。其中最主要的方法是await和countDown,调用await()的线程如果CountDownLatch内部count变量不为0,则一直阻塞,直到为0,并且可以有多个线程调用await(),也就是多个线程同时等待。

下面的例子先创建两个线程,一直等待,然后启动10个线程对CountDownLatch进行减少。10次countDown()后,前两个线程才可以运行。

public class Main2 { static CountDownLatch countDownLatch = new CountDownLatch(10);
public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 2; i++) { new Thread(() -> { try { System.out.println(Thread.currentThread()+" start");                    countDownLatch.await(); } catch (InterruptedException e) {                    e.printStackTrace(); } System.out.println(Thread.currentThread() + " end");
}).start(); } Thread.sleep(2000);        startThreads(); }
private static void startThreads() { for (int i = 0; i < 10; i++) { new Thread(() -> {                countDownLatch.countDown(); try { Thread.sleep(500); } catch (InterruptedException e) {                    e.printStackTrace(); } }).start(); } }}

CyclicBarrier

和CountDownLatch类似,也实现了线程间的计数等待,同样调用其await()让线程阻塞,但是区别是只有当其他线程也调用await()直到数量为计数总数时才得到运行。并且提供了复位方法reset()。

比如和朋友开黑,5名朋友依次来网吧,来的人要等待没来的,到齐后,一起说声联盟万岁。

public class Main2 { public static void main(String[] args) throws InterruptedException { CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> { System.out.println("可以开黑了"); }); for (int i = 0; i < 5; i++) { new Friend(cyclicBarrier).start(); System.out.println("还剩" + (cyclicBarrier.getParties() - cyclicBarrier.getNumberWaiting()) + " 人"); Thread.sleep(1000);
} }
static class Friend extends Thread { CyclicBarrier mCyclicBarrier;
public Friend(CyclicBarrier cyclicBarrier) {            mCyclicBarrier = cyclicBarrier; }
@Override public void run() { super.run(); String msg = (mCyclicBarrier.getParties() - mCyclicBarrier.getNumberWaiting() == 1) ? "最后一位到了" : "等待其他队友"; System.out.println(Thread.currentThread() + msg); try {                mCyclicBarrier.await(); System.out.println("联盟万岁"); } catch (InterruptedException e) {                e.printStackTrace(); } catch (BrokenBarrierException e) {                e.printStackTrace(); } } }}
还剩5 人Thread[Thread-0,5,main]等待其他队友还剩4 人Thread[Thread-1,5,main]等待其他队友还剩3 人Thread[Thread-2,5,main]等待其他队友还剩2 人Thread[Thread-3,5,main]等待其他队友还剩1 人Thread[Thread-4,5,main]最后一位到了可以开黑了联盟万岁联盟万岁联盟万岁联盟万岁联盟万岁

区别

对于CountDownLatch,等待条件完成后执行者是其他线程,而CyclicBarrier是本身,并且CyclicBarrier可循环使用,提供了reset()来复位,但是会导致await()的线程抛出BrokenBarrierException异常。

也就是说CountDownLatch是一个或者多个线程在等待其他线程,而CyclicBarrier是多个线程互相等待。