ZetCode

Java CountDownLatch

最后修改日期:2024 年 7 月 15 日

在本文中,我们将展示如何使用 CountDownLatch 同步 Java 线程。

CountDownLatch 是一个用于线程同步的类。它允许一个线程(通常是主线程)等待一定数量的其他线程完成执行后再继续。

要使用 CountDownLatch,我们首先创建一个 CountDownLatch 对象,并用一个初始计数表示我们要等待的线程数。每个需要同步的线程都调用 latch 对象的 countDown 方法。这实际上标志着它们已完成。

主线程或任何其他等待线程,在 latch 上调用 await 方法。此方法会阻塞调用线程,直到 latch 的内部计数器达到零。

CountDownLatch 示例

以下示例显示了 CountDownLatch 的用法。

Main.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Stream;


class Worker implements Runnable {

    private final List<String> messages;
    private final CountDownLatch countDownLatch;

    public Worker(List<String> messages, CountDownLatch countDownLatch) {
        this.messages = messages;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {

        int r = new Random().nextInt(3000, 8000);

        System.out.printf("%s starting, durations %dms %n", 
            Thread.currentThread().getName(), r);

        try {
            Thread.sleep(r);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println(Thread.currentThread().getName() + " completed");
        messages.add(Thread.currentThread().getName() + " completed");
        countDownLatch.countDown();
    }
}

void main() throws InterruptedException {

    List<String> messages = Collections.synchronizedList(new ArrayList<>());
    var countDownLatch = new CountDownLatch(5);
    List<Thread> workers = Stream.generate(() -> 
        new Thread(new Worker(messages, countDownLatch)))
            .limit(5)
            .toList();

    workers.forEach(Thread::start);
    countDownLatch.await();
    messages.add("Latch released");

    System.out.println(messages);
}

主线程创建五个新线程;这五个线程使用 CountDownLatch 进行同步。

int r = new Random().nextInt(3000, 8000);

每个线程运行一个介于 3000 和 8000 毫秒之间的随机毫秒数。

messages.add(Thread.currentThread().getName() + " completed");
countDownLatch.countDown();

任务完成后,它会将消息写入同步列表,并使用 countDown 递减 latch 的计数。如果计数达到零,则所有等待线程都将被释放。

List<String> messages = Collections.synchronizedList(new ArrayList<>());
var countDownLatch = new CountDownLatch(5);

我们创建一个同步列表和一个用于五个任务的 CountDownLatch

List<Thread> workers = Stream.generate(() -> 
    new Thread(new Worker(messages, countDownLatch)))
        .limit(5)
        .toList();

创建包含五个线程的列表。每个线程都接收一个同步消息列表和 countDownLatch

workers.forEach(Thread::start);

我们启动所有线程。

countDownLatch.await();

除非线程被中断,否则 await 方法会导致主线程等待,直到 latch 计数到零。

System.out.println(messages);

最后,我们打印所有消息。

来源

Java CountDownLatch - 参考

在本文中,我们展示了如何使用 CountDownLatch 同步 Java 线程。

作者

我叫 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我从 2007 年开始撰写编程文章。 迄今为止,我撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有Java教程