从CompletableFuture取值时Sonar的InterruptedException问题解决方案咨询
解决方案
方案1:用CompletableFuture.join()替代get()
CompletableFuture.join()和get()功能类似,但不会抛出检查型异常(包括InterruptedException),只会把异常包装成未检查的CompletionException抛出。这样既不用处理中断异常,也能满足Sonar的规则,同时继续处理其他Future:
private void mapFutures( Map<Obj1, CompletableFuture<DummyContainer>> futures, List<DummyStatus> dummyStatusList) { for (Map.Entry<Obj1, CompletableFuture<DummyContainer>> entry : futures.entrySet()) { try { Optional<DummyContainer> dummyContainer = Optional.ofNullable(entry.getValue().join()); List<Dummy> dummy = dummyContainer.map(DummyContainer::getDummyData).orElse(null); if (!CollectionUtils.isEmpty(dummy)) { dummyStatusList.add(new DummyStatus(entry.getKey(), dummy.get(0))); } else { dummyStatusList.add(new DummyStatus(entry.getKey())); } } catch (CompletionException e) { // 记录日志后跳过当前Future,继续处理下一个 log.warn("处理Future失败,key: {}", entry.getKey(), e); } } }
方案2:捕获中断异常后重置状态,继续循环
如果必须使用get(),可以在捕获InterruptedException后先重置中断状态(满足Sonar的强制要求),然后跳过当前迭代继续处理其他Future:
private void mapFutures( Map<Obj1, CompletableFuture<DummyContainer>> futures, List<DummyStatus> dummyStatusList) { for (Map.Entry<Obj1, CompletableFuture<DummyContainer>> entry : futures.entrySet()) { try { Optional<DummyContainer> dummyContainer = Optional.ofNullable(entry.getValue().get()); List<Dummy> dummy = dummyContainer.map(DummyContainer::getDummyData).orElse(null); if (!CollectionUtils.isEmpty(dummy)) { dummyStatusList.add(new DummyStatus(entry.getKey(), dummy.get(0))); } else { dummyStatusList.add(new DummyStatus(entry.getKey())); } } catch (ExecutionException e) { log.warn("Future执行失败,key: {}", entry.getKey(), e); } catch (InterruptedException e) { // 重置中断状态,符合Sonar规则 Thread.currentThread().interrupt(); // 记录日志后继续处理下一个Future log.warn("线程被中断,跳过当前Future处理,key: {}", entry.getKey(), e); } } }
方案3:提前用exceptionally()处理异常
在创建Future的时候,就通过exceptionally()指定异常场景的默认返回值,后续处理时直接拿到结果,无需捕获异常:
// 创建futures时提前处理异常 Map<Obj1, CompletableFuture<DummyContainer>> futures = ...; futures.replaceAll((key, future) -> future.exceptionally(ex -> { log.warn("Future执行异常,key: {}", key, ex); return null; // 异常时返回null,后续会被Optional包装为empty })); // 简化后的mapFutures方法 private void mapFutures( Map<Obj1, CompletableFuture<DummyContainer>> futures, List<DummyStatus> dummyStatusList) { for (Map.Entry<Obj1, CompletableFuture<DummyContainer>> entry : futures.entrySet()) { Optional<DummyContainer> dummyContainer = Optional.ofNullable(entry.getValue().join()); List<Dummy> dummy = dummyContainer.map(DummyContainer::getDummyData).orElse(null); if (!CollectionUtils.isEmpty(dummy)) { dummyStatusList.add(new DummyStatus(entry.getKey(), dummy.get(0))); } else { dummyStatusList.add(new DummyStatus(entry.getKey())); } } }
内容的提问来源于stack exchange,提问作者Shailja
相关产品推荐
相关产品推荐

