如何用CompletableFuture.anyOf获取返回true的异步任务对应ID并过滤false结果
解决方案
问题1:获取返回true对应的输入ID
原代码仅返回Boolean结果,丢失了对应的输入ID信息。核心解决思路是把ID和结果绑定在一起返回,可以用JDK自带的AbstractMap.SimpleEntry,也可以自定义一个DTO类来封装这两个值。
示例代码:
// 用SimpleEntry封装ID和对应结果,也可以自定义如ResultDTO(Integer id, Boolean result)的类 CompletableFuture<Map.Entry<Integer, Boolean>> future1 = CompletableFuture.supplyAsync(() -> new AbstractMap.SimpleEntry<>(1, myService.myMethod(1)) ); CompletableFuture<Map.Entry<Integer, Boolean>> future2 = CompletableFuture.supplyAsync(() -> new AbstractMap.SimpleEntry<>(2, myService.myMethod(2)) ); CompletableFuture<Map.Entry<Integer, Boolean>> future3 = CompletableFuture.supplyAsync(() -> new AbstractMap.SimpleEntry<>(3, myService.myMethod(3)) ); CompletableFuture<Map.Entry<Integer, Boolean>> future4 = CompletableFuture.supplyAsync(() -> new AbstractMap.SimpleEntry<>(4, myService.myMethod(4)) ); // 将所有Future收集到列表,方便后续统一处理 List<CompletableFuture<Map.Entry<Integer, Boolean>>> futures = Arrays.asList(future1, future2, future3, future4);
这样每个异步任务完成后,都会返回包含输入ID和对应结果的Entry,后续处理时就能直接拿到关联的ID。
问题2:跳过false结果,等待第一个true结果
CompletableFuture.anyOf()会返回第一个完成的Future,不管结果是true还是false,无法满足“跳过false,直到找到第一个true”的需求。需要监听每个Future的完成事件,过滤掉false结果,一旦找到true就立即返回,同时取消其他未完成的任务以节省资源。
实现代码:
public static CompletableFuture<Map.Entry<Integer, Boolean>> findFirstTrueResult(List<CompletableFuture<Map.Entry<Integer, Boolean>>> futures) { CompletableFuture<Map.Entry<Integer, Boolean>> resultFuture = new CompletableFuture<>(); // 给每个Future添加完成回调 for (CompletableFuture<Map.Entry<Integer, Boolean>> future : futures) { future.whenComplete((entry, throwable) -> { // 有异常直接跳过(可根据业务需求调整异常处理逻辑) if (throwable != null) { return; } // 如果结果为true,且最终结果还未确定,就设置结果并取消其他未完成任务 if (entry.getValue() && !resultFuture.isDone()) { resultFuture.complete(entry); futures.stream().filter(f -> !f.isDone()).forEach(f -> f.cancel(false)); } // 所有任务都完成但没有true结果时,根据需求处理(这里返回null) else if (allFuturesDone(futures) && !resultFuture.isDone()) { resultFuture.complete(null); } }); } return resultFuture; } // 辅助方法:判断所有Future是否都已完成 private static boolean allFuturesDone(List<CompletableFuture<?>> futures) { return futures.stream().allMatch(CompletableFuture::isDone); }
使用方式:
// 创建带ID的Future列表 List<CompletableFuture<Map.Entry<Integer, Boolean>>> futures = Arrays.asList( CompletableFuture.supplyAsync(() -> new AbstractMap.SimpleEntry<>(1, myService.myMethod(1))), CompletableFuture.supplyAsync(() -> new AbstractMap.SimpleEntry<>(2, myService.myMethod(2))), CompletableFuture.supplyAsync(() -> new AbstractMap.SimpleEntry<>(3, myService.myMethod(3))), CompletableFuture.supplyAsync(() -> new AbstractMap.SimpleEntry<>(4, myService.myMethod(4))) ); // 获取第一个返回true的结果及对应ID CompletableFuture<Map.Entry<Integer, Boolean>> firstTrueFuture = findFirstTrueResult(futures); // 处理最终结果 try { Map.Entry<Integer, Boolean> result = firstTrueFuture.get(); if (result != null) { System.out.println("第一个返回true的ID:" + result.getKey() + ",结果:" + result.getValue()); } else { System.out.println("所有调用均返回false"); } } catch (InterruptedException | ExecutionException e) { // 处理异常 e.printStackTrace(); }
关键说明:
- 结果绑定:确保异步任务的结果与输入ID强关联,避免信息丢失。
- 高效终止:找到第一个true结果后立即取消其他未完成任务,避免无用计算。
- 边界处理:所有任务完成但无true结果时,需根据业务需求做兜底处理(如返回null或抛出异常)。
内容的提问来源于stack exchange,提问作者Pooya Mirzapour
相关产品推荐
相关产品推荐

