我正在尝试构建FutureBuilder类,以简化链接期货。在此过程中,我试图了解使用Await的后果。
所以如果我有Mappers就是这样的话 F1(future1) - > F2 - > F3
F1:构建对象Foo
F2:转到数据库,将值Bar添加到Foo
F3:将包含Foo的消息发送到其他地方
我遇到的问题是F2,通常我会创建一个Future来从DB中获取Bar。在这种情况下,我已经在未来,所以在子未来上只有Await.result()
更容易,这样我就可以立即将它添加到Foo并将其传递给F3。 / p>
有问题吗?既然我将来会等待,我会通过等待锁定一个额外的线程吗?
OR是否应该完全采用不同的模式?请记住,我希望能够继续前进,以便在映射器中传递Foo对象,以便我可以轻松添加F4,5,6等。我知道我也可以将F3移动到F2并使用DB请求进行映射,但这也意味着我必须移动F4,5,6等。用它?
答案 0 :(得分:0)
有问题吗?因为我是将来的,所以我通过等待锁定一个额外的线程?
是的,你阻止了一个额外的线程: 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
答案 1 :(得分:0)
如果对象构造涉及多个阶段和多个阻塞调用,如DB调用,如果阻塞调用真的是一个关注点,而不是链接多个未来,我想知道为什么不使用actor。 Foo可以成为演员的状态。
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将在一个单独的线程中解决。我们无法在另一个线程中更新actor状态。 (众所周知关闭问题)
<强>超时强> 如果你需要在特定时间范围内发生的事情。 Ask模式结合Pipe模式将起到魔力。