• CountDownLatch本质其实就是一个计数器。
  • 在多线程并形处理业务时,需要等待其他线程处理完,再做后续的合并等操作,再响应用户时,可以使用CountDownLatch做计数,等到其他线程出现完之后,主线程就会被唤醒。
  • CountDownLatch本身就是基于AQS实现的。
  • new CountDownLatch时,直接指定好具体的数值。这个数值会复制给state属性。
  • 当子线程处理完任务后,执行countDown方法,内部就是直接给state - 1而已。
  • 当state减为0之后,执行await挂起的线程,就会被唤醒。
  • CountDownLatch不能重复使用

实现原理、应用场景

CountDownLatch的底层实现通常依赖于对底层的同步器(synchronizer)的使用,最常见的同步器是基于AQS(AbstractQueuedSynchronizer)的实现。

在AQS中,CountDownLatch使用一个共享的同步状态来表示等待的线程数。每个等待线程都调用await()方法来阻塞自己,直到计数器减为0。当一个线程调用countDown()方法时,计数器减一。一旦计数器达到零,所有被阻塞的线程将被同时释放,允许它们继续执行。

CountDownLatch的主要适用场景是在一个或多个线程等待其他线程完成某个操作,然后再继续执行的情况下。一些常见的应用场景包括:

  1. 主线程等待多个工作线程完成:当主线程需要等待多个工作线程完成某个任务后才能继续执行时,可以使用CountDownLatch。主线程可以调用await()方法来等待所有工作线程完成,并在所有工作线程调用countDown()方法后继续执行。
  2. 并发任务的协调:在并发编程中,当多个任务需要等待其他任务完成某个操作后再继续执行时,可以使用CountDownLatch来进行协调。每个任务可以在执行完自己的操作后调用countDown()方法,等待其他任务的任务可以在调用await()方法后阻塞自己,直到所有的任务都完成。
  3. 测试并发性能:在进行并发性能测试时,可以使用CountDownLatch来协调并发任务的开始和结束。测试线程可以在开始时调用await()方法等待所有任务准备就绪,然后同时释放所有任务开始执行。测试线程还可以在结束时调用await()方法等待所有任务执行完毕,然后进行性能统计和结果分析。

总的来说,CountDownLatch是一种用于多个线程之间进行协调和同步的工具,适用于一些需要等待其他线程完成某个操作后才能继续执行的场景。它能够有效地控制线程的执行顺序和并发性,提供了一种简单而灵活的线程间通信方式。

代码示例

下面是一个使用CountDownLatch的代码示例,展示了如何在多个线程之间进行同步等待:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        int threadsCount = 3;
        CountDownLatch latch = new CountDownLatch(threadsCount);

        for (int i = 0; i < threadsCount; i++) {
            Thread thread = new Thread(new Worker(latch));
            thread.start();
        }

        System.out.println("等待所有线程完成...");
        latch.await(); // 主线程等待所有工作线程完成

        System.out.println("所有线程已完成");
    }

    static class Worker implements Runnable {
        private final CountDownLatch latch;

        public Worker(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {
            // 模拟工作
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + " 完成工作");

            // 完成工作,倒计时减一
            latch.countDown();
        }
    }
}

在上述示例中,我们创建了一个CountDownLatch对象并初始化为3(threadsCount)。然后,我们创建了3个工作线程(Worker),每个线程在完成工作后调用CountDownLatch的countDown()方法将倒计时减一。

主线程调用CountDownLatch的await()方法来等待所有工作线程完成。在所有工作线程都调用了countDown()方法之后,倒计时减为0,await()方法返回,主线程继续执行后续操作。

输出示例:

等待所有线程完成...
Thread-0 完成工作
Thread-1 完成工作
Thread-2 完成工作
所有线程已完成

通过CountDownLatch,我们可以实现多个线程之间的同步等待,主线程可以在所有工作线程完成后继续执行。这对于协调多个线程的并发任务非常有用。