Java 8使用CompletableFuture :: join维护流顺序

时间:2015-10-27 07:19:46

标签: java java-8 java-stream completable-future

我有一个异步执行的查询输入流。我想确保当我使用Completablefuture::join时,按输入查询流的顺序收集这些需求的结果。

这就是我的代码的样子:

queries.stream()
     .map(query -> CompletableFuture.supplyAsync(() -> {
                    try {
                        return SQLQueryEngine.execute(query);
                    } catch (InternalErrorException e) {
                        throw new RuntimeException(e);
                    }
     }))
     .map(CompletableFuture::join)
     .collect(Collectors.toList());

SQLQueryEngine.execute(查询);返回List<Results>,因此输出为List<List<Result>。我想将所有结果展平并合并到一个列表中。如果我在收集之前使用.flatMap(List :: stream)来展平,它会保持排序吗?

1 个答案:

答案 0 :(得分:4)

你可能意味着.flatMap,是的,它会保留排序。

考虑明确地将Executor传递给supplyAsync,以避免在ForkJoinPool.commonPool()中调度IO绑定的sql查询。

作为@Ruben pointed out,您在提交后立即加入当前线程中的每个任务,并在提交下一个查询之前,这可能是一个错误。您应该先提交所有查询,然后才开始加入。

您可以这样做(使用静态导入toList):

queries.stream()
    .map(query -> CompletableFuture.supplyAsync(...))
    .collect(toList())
    .stream()
    .map(CompletableFuture::join)
    .collect(toList());