CountdownLatch 同步计数器
是同步器的一种, 也是基于AQS实现的. 是一种倒计时同步器. 当倒计时为0时, 唤醒所有工作线程.
- await(): 等待计数值变为0。如果计数值大于0,则线程会阻塞等待。
- countDown(): 将计数值减1。当计数值变为0时,所有等待的线程将被唤醒。countDown()一定要在方法的末尾调用, 如果在前面调用, 有可能逻辑没有执行完, 计数就减掉了, 导致提前唤醒主线程.
- 如果工作线程达不到 new CountdownLatch的数量, 那么主线程将一直处于阻塞状态, 来等待countdownLatch的计数减为0
- CountdownLatch 只能使用一次, 当计数减为0之后, CountdownLatch无法将计数重新设置.
案例
import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;
public class CountdownLatchTest {
static Logger log = Logger.getLogger("zzzzzzzzz");
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
long n = 500L;
new Thread(() -> {
try {
log.info("线程1");
Thread.sleep(1000);
// 如果countDown方法在sleep之前调用, 那么主线程不会阻塞
latch.countDown();
log.info("线程1结束");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
new Thread(() -> {
try {
log.info("线程2");
Thread.sleep(1500);
latch.countDown();
log.info("线程2结束");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
/* 注释掉线程3, 主线程会一直处于阻塞状态
new Thread(() -> {
try {
log.info("线程3");
Thread.sleep(2000);
latch.countDown();
log.info("线程3结束");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
*/
latch.await();
System.out.println("主线程结束");
}
}