如何解决了解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::wait
或Condition::await
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。