未来嵌套是反模式吗?

0dxa2lsx  于 2021-07-05  发布在  Java
关注(0)|答案(3)|浏览(403)

我有一个 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() 打回电话?有人告诉我,我可能会陷入挂机状态。这是真的吗?为什么会这样?以更好的方式实现同样的目标还有什么选择?

xdyibdwo

xdyibdwo1#

你可能想要更像:
whenAllSucceed (future1, future2).run(...) 这个 Runnable 你传给 run 还是要打电话 future2.get . 尽管如此, whenAllComplete 有一些优势 addCallback 方法:
这个 addCallback 方法可能需要一个线程来阻塞 future2.get 直到 future2 完成了(这至少是一点资源浪费。如果线程用完,代码可能会挂起。或者,您可能尝试创建一个新线程并用 whenAllComplete ,您的 Runnable 在两个输入期货都完成之前不会运行,所以 future2.get 不会阻塞。 whenAllComplete 返回一个 Future . 你可以用它来检查错误。如果你取消它,它将取消两个输入期货。
还要注意的是 whenAllSucceed 如果多个输入失败,将记录。这并不总是可取的。如果不需要日志记录,您可能更喜欢 whenAllComplete . (希望有一天我们能提供一种关闭日志记录的方法。)

fiei3ece

fiei3ece2#

在回调(如future.get)中执行阻塞操作破坏了异步编程的思想,将异步程序变成普通的多线程程序。所以这确实是一个反模式。但是,如果确定get()不会阻塞,则可以调用get()。如果需要等待2个异步结果的回调,可以改用completablefuture:

CompletableFuture<X> future1 = ...
CompletableFuture<X> future2 = ...
CompletableFuture future3 = future1.thenCombineAsync(future 2, futureCallback, executor);
1u4esq0p

1u4esq0p3#

做一个 .get() 回调中的调用是非常常见的——这是您大多数时候想要做的——但是更标准的模式是使用 transform 或者 transformAsync 传入直接接受结果的函数。

相关问题