计数器:CountDownLatch 内部维护一个计数器,初始化时指定计数值
等待线程:调用 await() 方法的线程会等待,直到计数器变为 0
计数线程:调用 countDown() 方法的线程会将计数器减 1
一次性:CountDownLatch 的计数器不能被重置,是一次性的
package com.jysemel.java.lock;
import lombok.SneakyThrows;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
private static final int count = 200;
@SneakyThrows
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(3);
for (int i = 1; i <= 3; i++) {
new Thread(new Test(latch, "Test-" + i)).start();
}
System.out.println("主线程等待所有工作线程完成...");
latch.await();
System.out.println("所有工作线程已完成,主线程继续执行");
}
static class Test implements Runnable {
private final CountDownLatch latch;
private final String name;
public Test(CountDownLatch latch, String name) {
this.latch = latch;
this.name = name;
}
@Override
public void run() {
try {
System.out.println(name + " 开始工作");
Thread.sleep((long) (Math.random() * 2000));
System.out.println(name + " 工作完成");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
latch.countDown();
}
}
}
}
合理设置计数:不要设置过大的计数值,避免不必要的内存和性能开销
及时调用 countDown():确保在 finally 块中调用 countDown(),避免计数无法减少
避免长时间等待:使用带超时的 await() 方法,避免线程永久阻塞
考虑使用替代方案:对于需要重置的场景,考虑使用 CyclicBarrier
代码