返回

CountDownLatch,让并发编程达成等待与同步之美

后端

引子:裁判员等待所有运动员到来

想象一下,一场田径比赛即将开始,裁判员站在起跑线上,等待所有运动员全部到来后,才鸣枪发令。此时,裁判员扮演的角色与CountDownLatch在多线程编程中的作用十分相似。

CountDownLatch本质上是一个计数器,可以将一个线程阻塞,直到计数器减至0。与普通的计数器不同,CountDownLatch可以被多个线程同时操作,并提供线程安全保证。

CountDownLatch的工作原理

CountDownLatch的初始化需要传入一个整数参数,表示需要等待的任务数量。当某个线程调用countDown()方法时,计数器就会减1。当计数器减至0时,所有等待的线程都会被唤醒,继续执行。

CountDownLatch的使用场景

CountDownLatch适用于多种多线程编程场景,常见的有:

  • 等待所有线程完成任务: 如上文提到的裁判员等待所有运动员到达的场景,可以用CountDownLatch来实现。
  • 汇总多个线程的结果: 多个线程并行处理任务,当所有线程都完成后,汇总它们的结果。
  • 控制并发线程数量: 限制并发线程的数量,防止系统资源过载。

CountDownLatch的代码示例

CountDownLatch的使用非常简单,以下是一个示例代码:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchExample {
    public static void main(String[] args) {
        // 创建一个CountDownLatch,初始值为5
        CountDownLatch latch = new CountDownLatch(5);

        // 创建一个线程池,并提交5个任务
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            executorService.submit(() -> {
                // 模拟任务执行,随机休眠0-2秒
                try {
                    Thread.sleep((long) (Math.random() * 2000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 任务执行完成后,调用countDown()方法减少计数器
                latch.countDown();
            });
        }

        // 主线程等待所有任务完成
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 所有任务完成后,执行后续操作
        System.out.println("所有任务完成,继续执行后续操作...");

        // 关闭线程池
        executorService.shutdown();
    }
}

总结

CountDownLatch是一个非常有用的同步工具,它可以帮助多线程程序实现等待和同步。在本文中,我们介绍了CountDownLatch的工作原理、使用场景和代码示例。掌握CountDownLatch的用法,可以帮助您编写更可靠、更健壮的多线程程序。