Java 对象一旦无法访问就有资格进行垃圾回收,我的困惑是无法访问的 CompletableFutures 会发生什么,如下所示:
void someMethod(){
methodThatProduceCompletableFuture()
.thenAccept(s -> //produce some side effect);
}
对 someMethod 的调用可能会在 CompletableFuture 完成之前返回,因为没有人持有对 CompletableFuture 的引用,这个 CompletableFuture 会在完成之前被垃圾回收吗?
你的问题的答案是这样的:“如果没有人持有对 CompletableFuture 的引用,那么它总是会在被垃圾收集之前完成吗?”是不,它永远不会完成。如果没有人持有对 CompletableFuture 的引用,那么某人就不可能在所述 future 上调用
complete()
。
不过,我认为这不是你问题的意图。让我猜一下预期的上下文并重新表述一下:
“如果我的代码没有显式引用 CompletableFuture,它会在垃圾收集之前完成吗?”
答案是,视情况而定。让我们用你的例子。
void someMethod(){
methodThatProduceCompletableFuture()
.thenAccept(s -> //produce some side effect);
}
首先关注
methodThatProduceCompletableFuture()
,如果这个方法所做的只是创造一个空的未来——
CompletableFuture<Boolean> methodThatProduceCompletableFuture() {
return new CompletableFuture<>();
}
那么这将在完成之前被垃圾收集。没有人拥有对返回的未来的引用。因此,它既符合垃圾收集的条件,又无法完成。 但是,如果你这样实现——
CompletableFuture<Boolean> methodThatProduceCompletableFuture() {
return CompletableFuture.supplyAsync(() -> someJobThatReturnsBoolean());
}
这是一个不同的故事。它可能看起来与第一个实现类似,但这里的关键区别是这个实现将产生一个引用未来的线程
。一旦该工作完成,它将在我们返回的未来上调用 complete()
。这就是让未来保持活力的参考。
thenAccept()
一开始可能看起来有所不同,但随后您意识到
methodThatProduceCompletableFuture()
生成的 CompletableFuture 必须持有对此 future 的引用,以便它在第一个 future 完成时运行。那么,答案可以归结为 methodThatProduceCompletableFuture()
是否会生成一个具有对其引用并会完成的 CompletableFuture。附录1
正如一开始提到的,如果一个对象没有被引用,它就不可能完成,因为无法访问
complete()
函数。
附录2即使在上面的
new CompletableFuture<>()
情况下,只要你在某个地方通过了那个未来并且有人计划完成它,那么你的操作链就是安全的。