在运行异步任务流时使用CompletableFuture的最佳方法是什么?

问题描述 投票:1回答:1

我有一个弹簧组件EventSvcFacade,它具有三个EventValidationSvc实现类实例的列表。这些类中的每一个都实现方法boolean validate(T request),采用相同的输入,但在输入上调用不同的API,处理结果,并返回布尔值。因此,此流程设计用于并发调用。我已经找到了两种从任务流中返回布尔值列表的方法。任何人都可以建议在哪种因素上比另一种方法更好,或者还有其他更好的方法?

@Component
public class EventSvcFacade {

    @Autowired
    private List<EventValidationSvc<EventRequest>> validationSvcs;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    public List<Boolean> firstApproach(){
      final List<CompletableFuture<Boolean>> futures = validationSvcs.stream().map(service -> 
            CompletableFuture.supplyAsync(() -> service.validate(eventRequest), threadPoolExecutor))
            .collect(Collectors.toList());                                                                                      
      final List<Boolean> values = futures.stream().map(CompletableFuture :: 
            join).collect(Collectors.toList());
      return values;
    }

    public List<Boolean> secondApproach() {
      final List<Boolean> values = Collections.synchronizedList(new ArrayList<>());
      final CountDownLatch countDownLatch = new CountDownLatch(validationSvcs.size());
      validationSvcs.stream().forEach(service -> CompletableFuture.runAsync(() -> {         
            try{
             values.add(service.validate(eventRequest));
            }finally{
             countDownLatch.countDown();
            }
          }, threadPoolExecutor)
      );
      countDownLatch.await();
      return values;
   }
}
java multithreading java-8 concurrency completable-future
1个回答
0
投票

第一种方法更干净,因为它是pure:由于它不依赖于副作用,因此以后修改代码时,更容易推理,也不太可能破坏代码。

而且第一种方法也不像第二种方法对CountDownLatch实例那样依赖于临时同步结构。如果您的前提条件发生变化,并且只有两个服务可以调用,则第一种方法将继续起作用,而第二种方法将永远不会返回。

© www.soinside.com 2019 - 2024. All rights reserved.