如何解决期货嵌套是一种反模式吗?
我有一个正在创建的ListenableFuture
,例如:
ListenableFuture<X> future1 = ...
ListenableFuture<X> future2 = ...
Futures.addCallback(future1,futureCallback,executor);
现在在futureCallback
里面:
public void onSuccess(Object result) {
Object f2 = future2.get();
.
.
. <do something with f2>
}
在回调中进行.get()
调用是否不好?有人告诉我我可能会陷入挂断状态。那是真的,为什么会这样呢?
以更好的方式实现同一目标的替代方法是什么?
解决方法
您可能想要更多类似的东西:
whenAllSucceed
(future1,future2).run(...)
您传递给Runnable
的{{1}}仍必须呼叫run
。与future2.get
方法相比,whenAllComplete
仍具有一些优势:
-
addCallback
方法可能需要一个线程来阻塞addCallback
,直到完成future2.get
。 (这至少会浪费少量资源。如果线程用完,则代码可能会挂起。或者您可能尝试创建新线程并用尽内存。)使用future2
,您的{{1 }}直到两个输入期货都完成后才会运行,因此whenAllComplete
不会被阻止。 -
Runnable
返回一个future2.get
。您可以使用它来检查错误。如果您取消它,它将同时取消两个输入期货。
还请注意,如果多个输入失败,whenAllComplete
将记录。这并不总是可取的。如果您不想记录日志,则可能更喜欢whenAllComplete
。 (希望有一天我们会provide a way to turn off the logging。)
在回调中进行.get()
调用是很平常的-这是您大多数时候想要做的-但更标准的模式是使用transform
或{{ 3}}传递直接采用结果的函数。
在回调函数(例如future.get)中执行阻塞操作破坏了异步编程的思想,将异步程序转换为普通的多线程。因此,这确实是一种反模式。 但是,如果确定不会阻塞,则可以调用get()。 如果您需要一个等待2个异步结果的回调,则可以改用CompletableFuture:
CompletableFuture<X> future1 = ...
CompletableFuture<X> future2 = ...
CompletableFuture future3 = future1.thenCombineAsync(future 2,futureCallback,executor);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。