CountDownLatch 注意事项

先看一段代码:


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()无法被执行,于是程序就一直阻塞在

countDownLatch.await();

正确的写法:

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、等都应该如此。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容