问题描述
在 Java 中使用 CompletableFuture,我意识到在 CompletableFuture 上使用 thenAccept 或其他同步方法非常棘手,如本网站所述:https://mobiarch.wordpress.com/2018/09/07/understanding-java-completablefuture/。我逐字引用:
对于像 thenAccept 这样的非异步方法,事情并不那么简单。 Java 使用此策略: 如果调用 thenAccept() 的未来在调用之前已经完成,那么 lambda 将在调用 thenAccept() 的同一线程中调用。 如果调用 thenAccept() 时未完成尚未完成,则将在完成未完成的同一线程中调用 lambda。在我们的例子中,这将是来自默认 ForkJoinPool 的线程”。 基本上非异步方法试图避免任何不必要的线程切换。这具有更少的 cpu 开销并且运行速度更快。但是如果 lambda 需要很长时间才能完成,我们就有阻塞主线程的风险。
我认为这是一个非常意外的行为,没有很好的文档记录和棘手,因为我创建了一些 CompletableFuture 来运行一个异步任务,以便从中返回一些东西,然后使用 thenAccept 等待该任务完成,并使用 lambda 函数获取结果返回给客户端。但是 lambda 函数没有在主线程中执行,导致向客户端返回了一些默认值,而不是计算出来的值。
谢谢
解决方法
答案很简单,而且已经讨论了很多here。
如果您希望确定性在哪个线程中执行您的操作,请使用 thenApplyAsync/thenAcceptAsync/etc
版本。