我有一个 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()
打回电话?有人告诉我,我可能会陷入挂机状态。这是真的吗?为什么会这样?以更好的方式实现同样的目标还有什么选择?
3条答案
按热度按时间xdyibdwo1#
你可能想要更像:
whenAllSucceed
(future1, future2).run(...)
这个Runnable
你传给run
还是要打电话future2.get
. 尽管如此,whenAllComplete
有一些优势addCallback
方法:这个
addCallback
方法可能需要一个线程来阻塞future2.get
直到future2
完成了(这至少是一点资源浪费。如果线程用完,代码可能会挂起。或者,您可能尝试创建一个新线程并用whenAllComplete
,您的Runnable
在两个输入期货都完成之前不会运行,所以future2.get
不会阻塞。whenAllComplete
返回一个Future
. 你可以用它来检查错误。如果你取消它,它将取消两个输入期货。还要注意的是
whenAllSucceed
如果多个输入失败,将记录。这并不总是可取的。如果不需要日志记录,您可能更喜欢whenAllComplete
. (希望有一天我们能提供一种关闭日志记录的方法。)fiei3ece2#
在回调(如future.get)中执行阻塞操作破坏了异步编程的思想,将异步程序变成普通的多线程程序。所以这确实是一个反模式。但是,如果确定get()不会阻塞,则可以调用get()。如果需要等待2个异步结果的回调,可以改用completablefuture:
1u4esq0p3#
做一个
.get()
回调中的调用是非常常见的——这是您大多数时候想要做的——但是更标准的模式是使用transform
或者transformAsync
传入直接接受结果的函数。