我正在尝试构建一个FutureBuilder类来简化chaining Futures。在这个过程中,我试图理解使用Await的后果。
因此,如果我有类似F1(future1) -> F2 -> F3的映射器
F1:构建对象Foo
F2:转到数据库以将值栏添加到Foo
F3:将包含Foo的消息发送到其他地方
我遇到的问题是F2,通常我会创建一个从数据库获取栏的未来。在这种情况下,我已经在一个Future中,所以在sub-future上更容易只是一个Await.result(),这样我就可以立即将它添加到Foo并传递给F3。
这有什么问题吗?因为我已经在将来了,所以我会通过等待来锁定额外的线程吗?
或者我应该做一个完全不同的模式?请记住,我希望能够继续下去,所以在映射器中传递Foo对象,以便我可以轻松地添加F4,5,6等。我知道我也可以将F3移动到F2中,并使用DB请求进行映射,但这也意味着我必须使用它移动F4,5,6等?
发布于 2017-07-11 05:31:42
这有什么问题吗?因为我已经在将来了,所以我会通过等待来锁定额外的线程吗?
是的,你正在阻塞一个额外的线程:http://doc.akka.io/docs/akka/current/java/futures.html#use-with-actors
警告
Await.result和Await.ready是为您必须阻止的特殊情况提供的,一个好的经验法则是只有在您知道为什么必须阻止的情况下才使用它们。
我只在测试代码中使用Await。
该文档的以下部分描述了如何将期货链接在一起。如果你可以使用Java 8,它会变得更好,详情请看这一节:
http://doc.akka.io/docs/akka/current/java/futures.html#java-8-completionstage-and-completablefuture
发布于 2017-07-13 07:09:36
如果对象构造涉及多个阶段和多个阻塞调用,比如DB调用,那么如果阻塞调用真的是一个问题,那么我想知道为什么不使用actors,而不是链接多个未来。Foo可以是参与者的State。
object Data {
case class Foo(var1: String, var2: String, ..)
// commands or messages
case object doF1
case object doF2
//...
}
class FutureChainAlternative extends Actor {
def receive = {
case doF1 =>
// perform what F1 should do.
// pipe the result back to self
f1.map(f1Result => preferredFormatConvertorOrProcessorForF1) pipeTo self
case preferredFormatConvertorOrProcessorF1 =>
// update the Foo object with F1 results
self ! doF2
case doF2 =>
// perform what F2 should do.
// pipe the result back to self
f2.map(f2Result => preferredFormatConvertorOrProcessorForF2) pipeTo self
}
}为什么我们需要单独的消息preferredFormatConvertorOrProcessorF1 ? F1在完成时将在单独的线程中解析。我们不能在另一个线程中更新参与者的状态。(众所周知的关闭问题)
如果您需要在特定的时间范围内发生事情,则可以使用Timeout。Ask模式和Pipe模式的结合将会产生神奇的效果。
https://stackoverflow.com/questions/45021662
复制相似问题