深耕 JDK 源码 - CountDownLatch

2023-04-21  本文已影响0人  西瓜汁and柠檬水

多线程编程中,线程之间的协同与同步是一种常见的需求。Java 提供了许多用于实现线程同步的工具,其中之一就是 CountDownLatch。CountDownLatch 是一个简单而强大的多线程同步工具,可以帮助开发者实现一组线程在某个事件完成后再同时执行的需求。本文将详细介绍 CountDownLatch 的实现原理、用法以及相关的代码解释。

一、实现原理

CountDownLatch 内部维护了一个计数器,通过其构造方法指定初始计数值。计数器的值在 CountDownLatch 对象创建后是不可修改的。每当一个线程完成了某个任务时,可以调用 CountDownLatch 的 countDown() 方法,将计数值减一。当计数值变为零时,所有在 CountDownLatch 上等待的线程会被唤醒,可以继续执行。

CountDownLatch 的实现原理可以简单描述如下:

  1. 创建 CountDownLatch 对象时,需要指定初始计数值。
  2. 每个线程在完成任务后,通过调用 countDown() 方法将计数值减一。
  3. 当计数值变为零时,所有等待的线程会被唤醒,可以继续执行后续的逻辑。

二、用法

CountDownLatch 常用于一组线程中,有一个或多个线程需要等待其他线程完成某个任务后再继续执行。以下是 CountDownLatch 的一般用法:

  1. 创建 CountDownLatch 对象,并指定初始计数值:
CountDownLatch latch = new CountDownLatch(3); // 初始计数值为 3

这里创建了一个 CountDownLatch 对象 latch,并指定初始计数值为 3。

  1. 创建需要等待的线程,并在其任务完成后调用 countDown() 方法:
// 线程1
Thread thread1 = new Thread(() -> {
    // 执行任务
    latch.countDown(); // 计数值减一
});

// 线程2
Thread thread2 = new Thread(() -> {
    // 执行任务
    latch.countDown(); // 计数值减一
});

// 线程3
Thread thread3 = new Thread(() -> {
    // 执行任务
    latch.countDown(); // 计数值减一
});

这里创建了三个线程 thread1、thread2、thread3,并在其任务完成后分别调用了 countDown() 方法,将计数值减一。

  1. 创建需要等待的线程,并在其任务完成后调用 await() 方法来等待其他线程完成任务:
// 等待线程1、线程2、线程3完成任务
try {
    latch.await(); // 等待计数值变为零
} catch (InterruptedException e) {
    // 处理中断异常
}

这里调用了 await() 方法,它会阻住当前线程,直到计数值变为零,即所有等待的线程都完成了任务。

  1. 完整示例代码:

下面是一个完整的示例代码,演示了 CountDownLatch 的使用:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {

    public static void main(String[] args) {
        // 创建 CountDownLatch 对象,并指定初始计数值为 3
        CountDownLatch latch = new CountDownLatch(3);

        // 创建线程1
        Thread thread1 = new Thread(() -> {
            System.out.println("Thread 1 is running...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 1 finished.");
            latch.countDown(); // 计数值减一
        });

        // 创建线程2
        Thread thread2 = new Thread(() -> {
            System.out.println("Thread 2 is running...");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 2 finished.");
            latch.countDown(); // 计数值减一
        });

        // 创建线程3
        Thread thread3 = new Thread(() -> {
            System.out.println("Thread 3 is running...");
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 3 finished.");
            latch.countDown(); // 计数值减一
        });

        // 启动线程
        thread1.start();
        thread2.start();
        thread3.start();

        try {
            latch.await(); // 等待计数值变为零
            System.out.println("All threads finished. Proceeding to next step.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行以上代码,会输出类似以下的结果:

Thread 3 is running...
Thread 1 is running...
Thread 2 is running...
Thread 3 finished.
Thread 1 finished.
Thread 2 finished.
All threads finished. Proceeding to next step.

三、总结

CountDownLatch 是一个简单而强大的多线程同步工具,可以帮助开发者实现一组线程在某个事件完成后再同时执行的需求。它的实现原理简单明了,通过维护一个计数器来实现线程之间的同步。通过调用 countDown() 方法将计数值减一,当计数值变为零时,所有等待的线程会被唤醒。CountDownLatch 在实际开发中可以应用于各种场景,例如等待多个线程完成初始化、等待多个线程同时开始执行某个任务等。使用 CountDownLatch 可以使多线程编程更加简洁、高效和安全。

上一篇下一篇

猜你喜欢

热点阅读