2017-08-08 71 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的結果。