关于CompletableFuture中两个后续调用是否同步执行的问询
问题解答
核心结论
你写的这两个调用不是同步执行,它们会在tweetFuture完成后各自独立启动,大概率是并行运行的。
原因分析
CompletableFuture的thenApply和thenCompose本质是注册回调任务:当上游的tweetFuture成功拿到List<Tweet>结果后,这两个回调会被同时调度执行:
tweetFuture.thenApply(tweetRepository::saveAll):触发数据库持久化操作tweetFuture.thenCompose(this::deleteTweets):触发另一个Web服务调用
这两个任务相互独立,默认会用ForkJoinPool的线程来执行,所以是并行跑的,不会等一个做完再启动另一个。
现有代码的问题
不过你的写法有两个明显的坑:
- 保存任务的状态完全丢失:你调用了
thenApply但没保存返回的CompletableFuture,导致根本没法知道保存操作有没有完成、有没有抛出异常。 - 返回结果只关联了删除任务:如果业务需要确保两个操作都完成后再返回,当前写法做不到;而且如果保存操作出问题,你完全感知不到。
优化写法
如果要确保两个操作都完成,同时保留并行特性,可以改成这样:
CompletableFuture<List<Tweet>> tweetFuture = CompletableFuture.supplyAsync(() -> restUtils.getTweetsByUserId(userId)) .thenApply(TweetConvertor::convertToTweet); // 分别保存两个异步任务的引用,方便跟踪状态 CompletableFuture<List<Tweet>> saveDbFuture = tweetFuture.thenApply(tweetRepository::saveAll); CompletableFuture<Void> callWebServiceFuture = tweetFuture.thenCompose(this::deleteTweets); // 等待两个任务都完成,再返回结果(可根据业务需求调整返回值) return CompletableFuture.allOf(saveDbFuture, callWebServiceFuture) .thenApply(ignored -> tweetFuture.join());
这样既能保证两个操作并行执行,又能完整跟踪它们的完成状态,方便后续统一处理结果或异常。
内容的提问来源于stack exchange,提问作者user3878073
相关产品推荐
相关产品推荐

