2017-08-08 73 views
0

我有一个演员p: ParentActor,我想要做一些清理工作,当它通过使用postStop方法停止。其中一项工作涉及向儿童演员c: ChildActor发送消息。之后,应该停止c,然后p。但是,一旦context.stop(p)被称为c似乎立即停止并且无法接收消息。不要立刻停止孩子Akka演员时,父母演员停止

下面是想我做的一个例子:

class ParentActor extends Actor { 
    ... 
    override def postStop { 
    logger.info("Shutdown message received. Sending message to child...") 
    val future = c ? "doThing" 
    logger.info("Waiting for child to complete task...") 
    Await.result(future, Duration.Inf) 
    context.stop(c) 
    logger.info("Child stopped. Stopping self. Bye!") 
    context.stop(self) 
    } 
} 

结果错误消息:

[ERROR] [SetSystem-akka.actor.default-dispatcher-5] [akka://SetSystem/user/ParentActor] Recipient[Actor[akka://SetSystem/user/ParentActor/ChildActor#70868360]] had already been terminated. Sender[Actor[akka://SetSystem/user/ParentActor#662624985]] sent the message of type "java.lang.String". 

另一种方法是发送p一条消息说要关机,有上述行为发生的结果,但使用内置的停止功能似乎更好。

PS。这是一个新的应用程序,因此欢迎使用设计替代品

回答

1

当演员A停止时,其子女确实在ApostStop挂钩被调用之前停止。事件当一个演员停止序列如下(从官方documentation):

分两步演员收益的终止:第一男主角暂停其邮箱处理和停止命令发送到所有的孩子,那么它一直处理来自其子的内部终止通知,直到最后一个消失,最后终止本身(调用postStop,倾倒邮箱,在DeathWatch上发布Terminated,告诉其主管)。

覆盖父母的postStop不会帮助您,因为您希望的关闭过程包括向孩子发送消息并等待答复。当父母终止时,孩子在父母的postStop运行之前停止。

如上所述,发送特定消息至ParentActor以启动关机是另一种方法。像下面的内容将工作:

import akka.pattern.pipe 

class ParentActor extends Actor { 
    ... 
    def receive = { 
    case Shutdown => 
     (c ? DoYourThing).mapTo[ThingIsDone].pipeTo(self) 
    case ThingIsDone => 
     logger.info("Child has finished its task.") 
     context.stop(self) 
    case ... 
    } 
} 

注意,应该避免在使用演员Await。相反,pipe对演员的Future的结果。