我正在尝试在我的Scala 2.11应用程序(使用Akka)中将一个子actor发送给顶级actor(PoisonPill
)并关闭整个JVM进程
我上传了this repo,以便您可以重现我所看到的内容。只需克隆它并运行Master
。
但基本上我们有./gradlew run
:
Driver
然后在object Driver extends App {
println("Starting upp the app...")
lazy val cortex = ActorSystem("cortex")
cortex.registerOnTermination {
System.exit(0)
}
val master = cortex.actorOf(Props[Master], name = "Master")
println("About to fire a StartUp message at Master...")
master ! StartUp
println("Fired! Actor system is spinning up...")
}
:
Child
当我运行class Child extends Actor {
override def receive = {
case MakeItHappen =>
println("Child will make it happen!")
context.parent ! PoisonPill
}
}
时,我看到以下输出:
./gradlew run
然而,JVM进程永远不会关闭。我本来期望./gradlew run
Starting a Gradle Daemon (subsequent builds will be faster)
:compileJava NO-SOURCE
:compileScala UP-TO-DATE
:processResources NO-SOURCE
:classes UP-TO-DATE
:run
Starting upp the app...
About to fire a StartUp message at Master...
Fired! Actor system is spinning up...
Stage Director has received a command to start up the actor system!
Child will make it happen!
<==========---> 80% EXECUTING
> :run
杀死PoisonPill
(以及Master
),退出/关闭actor系统,然后Child
命令(我在之后注册)演员系统终止)启动并退出JVM进程。
谁能告诉我们这里发生了什么?
答案 0 :(得分:2)
您正在停止Master
,但您没有关闭ActorSystem
。即使Master
是顶级演员(即由system.actorOf
创建的演员),停止它也不会终止ActorSystem
(请注意Master
本身有parent,所以它不是演员层次结构中的“最高”演员。)
终止ActorSystem
的正常方法是致电terminate
。如果您希望在Master
停止后关闭整个系统,那么您可以覆盖Master
的{{1}}挂钩并在那里调用postStop
。但是,在actor的生命周期钩子中调用context.system.terminate()
是有风险的。例如,如果在actor中抛出异常,并且actor的监督策略将其停止,那么您可能不打算在此时关闭整个系统。这样的设计不是很有弹性。
查看此pattern以“在合适的时间关闭演员系统。”