简体   繁体   English

使用可完成的期货处理实体清单

[英]Process List of entities using completable futures

I have a list of entities of type T . 我有一个类型为T的实体的列表。 I also have a functional interface which acts as Supplier which has the method to performTask on entity and send back the result R which looks like: 我也有一个充当Supplier的功能接口,该接口具有对实体执行performTask并将结果R发送回的方法,如下所示:
R performTask(T entity) throws Exception . R performTask(T entity) throws Exception

I want to filter both: the successful results and errors & exceptions coming out of it onto separate maps. 我想同时过滤:成功的结果和错误和异常都过滤到单独的地图上。 The code I wrote here is taking time, Kindly suggest what can be done. 我在这里编写的代码花费时间,请提出可以做什么的建议。

I am looping on the list of entities, then process their completable future one by one, which I think is not the right way to do. 我浏览了实体列表,然后逐个处理它们的可完成未来,我认为这不是正确的方法。 Can you all suggest what can be done here ? 大家可以建议在这里可以做什么吗?

private void updateResultAndExceptionMaps(List < T > entities, final TaskProcessor < T, R > taskProcessor) {

 ExecutorService executor = createExecutorService();
 Map < T, R > outputMap = Collections.synchronizedMap(new HashMap < T, R > ());
 Map < T, Exception > errorMap = new ConcurrentHashMap < T, Exception > ();
 try {

  entities.stream()
   .forEach(entity -> CompletableFuture.supplyAsync(() -> {
     try {
      return taskProcessor.performTask(entity);
     } catch (Exception e) {
      errorMap.put(entity, (Exception) e.getCause());
      LOG.error("Error processing entity Exception: " + entity, e);
     }
     return null;
    }, executor)
    .exceptionally(throwable -> {
     errorMap.put(entity, (Exception) throwable);
     LOG.error("Error processing entity Throwable: " + entity, throwable);
     return null;
    })
    .thenAcceptAsync(R -> outputMap.put(entity, R))
    .join()
   ); // end of for-each 

  LOG.info("outputMap Map -> " + outputMap);
  LOG.info("errorMap Map -> " + errorMap);
 } catch (Exception ex) {
  LOG.warn("Error: " + ex, ex);
 } finally {
  executor.shutdown();
 }
}

outputmap should contain the entity and result, R . outputmap应该包含实体和结果R
errorMap should contain entity and Exception . errorMap应该包含Entity和Exception

This is because you iterate over List of entities one by one, create CompletableFuture object and immediately block iteration because of join method which waits until given processor finishes it work or throw exception. 这是因为您要逐一遍历实体List ,创建CompletableFuture对象,并由于join方法而立即阻止迭代,因为join方法要等到给定处理器完成其工作或引发异常。 You can do that with full multithreading support by converting each entity to CompletableFuture , collect all CompletableFuture instances and after that wait for all invoking join on each. 您可以通过每个实体转换为做到这一点与完全支持多线程CompletableFuture ,收集所有CompletableFuture实例,之后等待所有调用join每个。

Below code should do the trick in your case: 下面的代码可以解决您的问题:

entities.stream()
    .map(entity -> CompletableFuture.supplyAsync(() -> {
            try {
                return taskProcessor.performTask(entity);
            } catch (Exception e) {
                errorMap.put(entity, (Exception) e.getCause());
            }
            return null;
        }, executor)
                .exceptionally(throwable -> {
                    errorMap.put(entity, (Exception) throwable);
                    return null;
                })
                .thenAcceptAsync(R -> outputMap.put(entity, R))
    ).collect(Collectors.toList())
    .forEach(CompletableFuture::join);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM