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

时间:2019-04-16 16:05:39

标签: java multithreading java-8 multiprocessing completable-future

我有一个T类型的实体的列表。我还具有一个用作Supplier的功能接口,该接口具有在实体上performTask并发送回结果R的方法,如下所示:
R performTask(T entity) throws Exception

我想同时过滤:成功的结果和错误和异常都过滤到单独的地图上。我在这里编写的代码需要花费时间,请提出建议。

我要遍历实体列表,然后逐个处理它们的可完成未来,我认为这不是正确的方法。你们都可以建议可以在这里做什么吗?

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应该包含实体和结果R
errorMap应包含实体和Exception

1 个答案:

答案 0 :(得分:0)

这是因为您逐个遍历List个实体,创建了CompletableFuture对象,并由于join方法而立即阻止了迭代,该方法一直等到给定处理器完成其工作或引发异常。您可以通过将每个实体转换为CompletableFuture,收集所有CompletableFuture实例,然后等待每个实例上的所有调用join来获得完整的多线程支持。

下面的代码应该可以解决您的问题:

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);