如何汇总在循环中进行CompletableFuture调用的结果?

时间:2017-07-04 00:27:23

标签: java asynchronous java-8 completable-future

我正在学习并尝试将CompletableFuture应用于我的问题陈述。我有一个我正在迭代的项目列表。

Prop是一个只有两个属性prop1和prop2的类,分别是getter和setter。

List<Prop> result = new ArrayList<>(); 

for ( Item item : items ) {
      item.load();

      Prop temp = new Prop();
      // once the item is loaded, get its properties
      temp.setProp1(item.getProp1());
      temp.setProp2(item.getProp2());

      result.add(temp);
}

return result;

但是,item.load()这里是一个阻塞调用。所以,我正在考虑使用下面的CompletableFuture -

for (Item item : items) {
    CompletableFuture<Prop> prop = CompletableFuture.supplyAsync(() -> {
        try {
            item.load();
            return item;
        } catch (Exception e) {
            logger.error("Error");
            return null;
        }
    }).thenApply(item1 -> {
        try {
            Prop temp = new Prop();
            // once the item is loaded, get its properties
            temp.setProp1(item.getProp1());
            temp.setProp2(item.getProp2());

            return temp;
        } catch (Exception e) {
        }
    });
}

但我不知道如何等待加载所有项目然后汇总并返回结果。

我实施CompletableFutures的方式可能完全错误,因为这是我的第一次尝试。请原谅任何错误。提前感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

您使用CompletableFuture的方法存在两个问题。

首先,你说item.load()是一个阻塞调用,因此CompletableFuture的默认执行程序不适合它,因为它试图达到与CPU核心数相匹配的并行度。您可以通过将不同的Executor传递给CompletableFuture的异步方法来解决此问题,但您的load()方法不会返回后续操作所依赖的值。因此CompletableFuture的使用使设计复杂化而没有任何好处。

您可以异步执行load()调用,只需使用ExecutorService等待完成,然后按原样循环(当然没有执行load()操作) :

ExecutorService es = Executors.newCachedThreadPool();
es.invokeAll(items.stream()
    .map(i -> Executors.callable(i::load))
    .collect(Collectors.toList()));
es.shutdown();

List<Prop> result = new ArrayList<>(); 

for(Item item : items) {
      Prop temp = new Prop();
      // once the item is loaded, get its properties
      temp.setProp1(item.getProp1());
      temp.setProp2(item.getProp2());

      result.add(temp);
}

return result;

您可以通过选择执行程序来控制并行度,例如:你可以使用Executors.newFixedThreadPool(numberOfThreads)代替无界线程池。