返回

CountDownLatch Java并发包源码深入解析

后端

CountDownLatch:多线程同步与通信的利器

简介

在多线程编程中,经常遇到线程同步和通信的问题。CountDownLatch 是一个用于解决这些问题的强大工具。它本质上是一个计数器,可以阻塞线程,直到计数器达到某个值。

CountDownLatch的用法

CountDownLatch的用法非常简单:

  1. 构造一个CountDownLatch实例,指定初始计数。
  2. 创建需要等待的线程。
  3. 在需要等待的代码段前调用CountDownLatch的 await()** ** 方法。**
  4. 在适当的时候调用CountDownLatch的 countDown()** ** 方法,减小计数器。**
  5. 计数器达到0时,所有等待线程将被唤醒。

CountDownLatch源码分析

CountDownLatch的源码并不复杂,但包含一些关键细节:

public class CountDownLatch {
    private final int count;
    private final AtomicLong state;

    public CountDownLatch(int count) {
        this.count = count;
        this.state = new AtomicLong(count);
    }

    public void await() throws InterruptedException {
        // 循环等待计数器为0
        while (true) {
            long current = state.get();
            if (current == 0) {
                return;
            }
            state.compareAndSet(current, current - 1);
            if (state.get() == 0) {
                return;
            }
            Thread.yield();
        }
    }

    public void countDown() {
        state.decrementAndGet();
    }
}

常见的应用场景

CountDownLatch可以用于解决多种多线程问题,包括:

  • 线程同步: 确保所有线程在执行关键操作之前完成特定任务。
  • 线程通信: 允许线程之间安全地交换数据。
  • 线程协作: 协调多个线程同时执行特定操作。

示例代码

以下代码演示了如何使用CountDownLatch来实现线程同步:

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

public class CountDownLatchDemo {

    private static final int THREAD_COUNT = 5;

    public static void main(String[] args) throws InterruptedException {
        // 创建一个CountDownLatch,初始计数为5
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);

        // 创建一个线程池
        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);

        // 创建5个线程并提交给线程池
        for (int i = 0; i < THREAD_COUNT; i++) {
            executorService.submit(() -> {
                try {
                    // 模拟每个线程执行一段任务
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 任务完成后,调用countDown()方法减小计数器
                    latch.countDown();
                }
            });
        }

        // 主线程等待所有子线程完成
        latch.await();

        // 所有子线程完成任务后,主线程继续执行
        System.out.println("所有线程已完成任务!");
    }
}

总结

CountDownLatch是一个简洁且强大的工具,可用于解决多线程同步和通信问题。它允许线程等待直到特定条件满足,并可用于协调和控制线程之间的交互。通过理解CountDownLatch的用法和实现,开发者可以编写出更加健壮和高效的多线程程序。

常见问题解答

  1. CountDownLatch与Semaphore有什么区别?
    • CountDownLatch是一次性的,计数器达到0后就不能再被增加,而Semaphore是一个可重用的计数器。
  2. CountDownLatch与CyclicBarrier有什么区别?
    • CountDownLatch用于线程同步,而CyclicBarrier用于线程协调,它允许线程在等待所有线程到达特定点后继续执行。
  3. CountDownLatch是否支持超时?
    • CountDownLatch的await()方法支持超时,但countDown()方法不支持。
  4. CountDownLatch是否线程安全?
    • CountDownLatch是线程安全的。
  5. CountDownLatch可以用于哪些应用场景?
    • CountDownLatch可用于实现线程同步、线程通信和线程协作。