CountDownLatch类是Java并发包(java.util.concurrent)中的一个同步工具类,它允许一个或多个线程等待直到在其他线程中执行的一组操作完成。

一、CountDownLatch的基本使用

在Java中,CountDownLatch主要有两种方法:await()和countDown()。await()方法会将当前线程阻塞,直到countDown()方法计数为0时才会唤醒。countDown()方法则是将计数器减1。

 import java.util.concurrent.CountDownLatch; public class Test { public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(2); new Thread(() -> { System.out.println("线程1开始执行"); latch.countDown(); System.out.println("线程1执行结束"); }).start(); new Thread(() -> { System.out.println("线程2开始执行"); latch.countDown(); System.out.println("线程2执行结束"); }).start(); latch.await(); System.out.println("所有线程执行完毕"); } } 

二、CountDownLatch的应用场景

由于CountDownLatch的特性,它通常用于等待其他一些线程完成工作后,当前线程再继续执行。这样可以有效控制任务的并发执行。常见的使用场景有初始化操作、多线程并发处理等。

 public class InitializedUsingLatch { private static CountDownLatch latch = new CountDownLatch(1); static class InitializeThread extends Thread { @Override public void run() { System.out.println("初始化操作..."); latch.countDown(); } } static class BusinessThread extends Thread { @Override public void run() { try { latch.await(); System.out.println("业务操作..."); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { new InitializeThread().start(); new BusinessThread().start(); new BusinessThread().start(); new BusinessThread().start(); } } 

三、CountDownLatch与CyclicBarrier的区别

虽然CountDownLatch和CyclicBarrier在一些场景下的功能相近,但两者有一些本质的区别。CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置。所以CyclicBarrier能处理更复杂的业务场景,比如如果一个复杂的处理流程需要分几个阶段依次执行。

 import java.util.concurrent.CyclicBarrier; public class CyclicBarrierDemo { public static void main(String[] args) { final CyclicBarrier barrier = new CyclicBarrier(3); for (int i = 0; i < 3; i++) { new Thread(() -> { System.out.println("线程" + Thread.currentThread().getName() + "等待"); try { barrier.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println("线程" + Thread.currentThread().getName() + "继续执行"); }).start(); } } }