CountDownLatch-注意事项

先看一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

CountDownLatch countDownLatch = new CountDownLatch(params.size());
try {
params.forEach(regionNameMapping -> {
CompletableFuture.runAsync(() -> {
Region region = this.getRegionById(regionNameMapping.getRegionId());
regionNameMapping.getRegionNameConsumer().accept(region.getName());
countDownLatch.countDown();
});
});
countDownLatch.await();
} catch (Exception e) {
log.error(e.getMessage(), e);
}

上面的代码逻辑很简单,并发去执行getRegionById这个方法。然后await等待结果。
但是里面有一个隐患,当region查出来为null时,会出现NPE,就会导致countDown()无法被执行,于是程序就一直阻塞在

1
2

countDownLatch.await();

正确的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CountDownLatch countDownLatch = new CountDownLatch(params.size());
try {
params.forEach(regionNameMapping -> {
CompletableFuture.runAsync(() -> {
try{
Region region = this.getRegionById(regionNameMapping.getRegionId());
regionNameMapping.getRegionNameConsumer().accept(region.getName());
}finally{
countDownLatch.countDown();
}
});
});
countDownLatch.await(3,TimeUnit.SECONDS);
} catch (Exception e) {
log.error(e.getMessage(), e);
}

添加try、finally,保证最终锁会被释放,以及设置等待超时时间,避免程序挂掉。

所有使用AbstractQueuedSynchronizer实现的同步器,例如Lock,Semaphore、等都应该如此。

作者

太阳当空赵先生

发布于

2019-07-10

更新于

2022-02-22

许可协议

评论