【问题标题】:How to wait until list of tasks are done using CompletableFuture ?如何使用 CompletableFuture 等到任务列表完成?
【发布时间】:2018-07-26 18:21:32
【问题描述】:

我正在试验 CompletableFutures,希望有人能帮助扭转局面。我的算法如下:

  1. 我有文章列表。
  2. 我调用 REST API 来获取每篇文章的类别。
  3. 我将类别保存到 DB。
  4. 我想并行执行第 2 步和第 3 步。

我想等到所有文章都处理完毕,所以在第二个 log.info() 之后没有异步完成任何工作。

我的代码如下:

    log.info("Starting CustomCommandLineRunner");

    List<Article> articles = articleService.getArticlesAvaialbleForAnalysis();

    List<CompletableFuture<Article>> futureArticlesList = articles.stream()
            .map(article -> {
                CompletableFuture<Map<String, Double>> futureCategoriesMap = categoryService.getArticleCategories(article.getUrl());
                return futureCategoriesMap.thenApply(categoriesMap -> articleService.setCatgoriesForArticle(article, categoriesMap));
            })
            .collect(Collectors.toList());

    CompletableFuture<Void> allArticlesFuture = CompletableFuture.allOf(futureArticlesList.toArray(new CompletableFuture[futureArticlesList.size()]));
    allArticlesFuture.get();

    log.info("Ended CustomCommandLineRunner");

不幸的是,articleService.setCatgoriesForArticle() 被调用了两次。你能把我推向正确的方向吗?

【问题讨论】:

  • 您是否尝试过使用ExecutorService?或者您是否尝试过使用CompletableFuture.isDone()
  • 附带说明,您可以使用更简单的CompletableFuture.allOf(futureArticlesList.toArray(new CompletableFuture[0]));;指定大小不会提高性能,请参阅this great article on that topic...

标签: java java-stream completable-future


【解决方案1】:

对于虚假的消防演习,我深表歉意。问题中的代码按预期工作。 articleService.setCatgoriesForArticle() 不会被调用两次,但 Spring @Transactional 不能很好地与 CompletableFutures 配合使用,这会导致同一实体的双重保存问题。

经验教训:不要将@Transactional 与异步代码混用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 2012-02-02
    相关资源
    最近更新 更多