我创造了一群做一些工作的演员,然后他们就被制止了。在其中一些演员中,我调用了返回Future
的第三方API。
MyActor extends Actor
{
....
def receive = {
case MsgA => {
...
//this evaluates to a Future
val p : Future = someFutureAPICall()
//stop the actor
context stop self
}
}
}
现在由于Future
非阻塞,即使Future
尚未完成,演员也会在此之后(?)停止。在这种情况下,预期的行为是什么?
例如,如果onComplete
上有Future
,即使演员已经停止,也会执行吗?
MyActor extends Actor
{
....
def receive = {
case MsgA => {
...
//this evaluates to a Future
val p : Future = someFutureAPICall()
p.onComplete {
//will these expressions ever be evaluated ?
case Success(x) => log.info("Success")
case Failure(f) => log.info("Failure")
}
//stop the actor
context stop self
}
}
}
答案 0 :(得分:8)
是的,返回Future(第三方API)的代码将立即执行并返回不完整的Future。
完成这个未来的执行与开始活着的演员没有任何关系。
如果你不再需要那个演员,你就不需要等待未来完成,你可以像第一个例子那样停止演员。
如果您需要在该actor中执行具有该未来结果的操作,您可以在该Future上安装onComplete
回调。一旦Future完成,它可以向演员发送消息以停止。例如:
val myActor = self // Don't close over unstable actor reference by using self directly
p.onComplete {
case Success(x) => myActor ! x; myActor ! akka.actor.PoisonPill // sends result to be processed and then stops actor
case Failure(f) => myActor ! akka.actor.PoisonPill // stops actor
}
修改
评论中建议的另一种方法是使用pipeTo
使用模式。它几乎完全相同。以下是它在Akka库中的实现方式:
def pipeTo(recipient: ActorRef)(implicit sender: ActorRef = Actor.noSender): Future[T] = {
future onComplete {
case Success(r) ⇒ recipient ! r
case Failure(f) ⇒ recipient ! Status.Failure(f)
}
future
}
以下是在创建Future之后如何调用它:
p pipeTo myActor
您的演员在收到消息后必须关闭自己的主要区别,并且失败显然会通过Failure
消息传达给演员。这种方法使用起来有点安全,因为你必须传递一个ActorRef
并且你不必记住将它(自己)复制到一个变量中。