了解CompletableFuture简单实现

问题描述

请考虑以下来自this article的代码。为了学习目的,它实现了类似于CompletableFuture的功能。

这是get()的{​​{1}}函数:

WaitingFuture

这是@Override public V get() throws ExecutionException { this.thread = Thread.currentThread(); LockSupport.park(this); if (throwable != null) { throw new ExecutionException(throwable); } return result; } 的{​​{1}}函数:

run()

问题:
在我看来,如果RunnableWaitingFuture将在@Override public void run() { try { waitingFuture.result = userFunction.get(); } catch (Throwable throwable) { waitingFuture.throwable = throwable; } finally { waitingFuture.finished = true; LockSupport.unpark(waitingFuture.thread); } } } 被调用之前完成,那么run()将在 get()之后被调用,从而使线程永远驻留

是真的吗?

解决方法

park() / unpark()wait / notify不同,因为如果在{{1}之前调用unpark不会丢失信号}}。

但是,仍然只有一点点不计入park()的呼叫频率,因此,假设所有呼叫都将完美配对仍然是错误的。

此外,unpark将在中断时静默返回,甚至允许虚假返回,这意味着没有理由。

换句话说,即使从park返回也不能保证已满足条件。就像其他通知机制一样,无法循环使用它。

所引用的代码更加糟糕,因为它还有一个关于park()变量的竞争条件。不能保证已在其他线程读取它时将其编写以通知它。

,

是。

LockSupport.park(this);

应替换为

while (!waitingFuture.finished) {
    LockSupport.park(this);
}

通常,LockSupport.park的功能太低,为了可靠性,应该使用Object::waitCondition::await

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...