如何使用CompletableFuture完成任务列表?

时间:2018-02-15 21:32:44

标签: java java-stream completable-future

我正在尝试使用CompletableFutures,并希望有人可以帮忙。我的算法如下:

  1. 我有文章列表。
  2. 我调用REST API来获取每篇文章的类别。
  3. 我将类别保存到数据库。
  4. 我想以并行的方式执行第2步和第3步。
  5. 我想等到所有文章都被处理完毕,所以在第二次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()调用了两次。你能不能把我推向正确的方向?

1 个答案:

答案 0 :(得分:0)

我为虚假的消防演员道歉。问题中的代码按预期工作。 articleService.setCatgoriesForArticle()未调用两次,但Spring @Transactional与CompletableFutures不能很好地兼容,这会导致同一实体的双重保存问题。

获得的经验:不要将@Transactional与异步代码混合。