例如,我有以下演员:Player
和GameRoom
。
GameRoom
让玩家得分。当用户离开(终止)时,我们将玩家得分保存在数据库中:
class Player extends Actor {
...
}
object GameRoom {
case object Join
}
class GameRoom(database:ActorRef) extends Actor {
type Score = Int
var players: Map[ActorRef, Score] = Map.empty
def receive: Receive = {
case GameRoom.Join =>
context.watch(sender())
players = players + (sender() -> 100)
case Terminated(player) =>
players = players - player
database ! SavePlayerScore(...)
}
}
但是如果我想杀死jvm进程(SIGTERM
)怎么办?在这种情况下,我无法在关机时将所有用户得分保存到数据库。
任何提示如何实现所需行为?
答案 0 :(得分:1)
您可以安装一个关闭钩子,在应用程序关闭时终止您的ActorSystem(使用ActorSystem#terminate())。
这将触发Actors层次结构的有序终止,从而导致GameRoom
收到Terminated
的{{1}}。
这是一个安装该关闭钩子的小代码片段:
players
这里需要注意的一件重要事情是:一旦Shutdown Hook中的代码完成,JVM将关闭(即使没有完成也会杀死所有线程),所以如果你有任何其他线程要清理,将其添加到关闭钩子。
编辑1 :即使 Runtime.getRuntime.addShutdownHook(
new Thread("shutdown-hook") {
override def run() {
// This obviously needs to
try{
Await.ready(actorSystem.terminate(), Duration(2, TimeUnit.MINUTES))
}catch{
case _ : InterruptedException => // Termination was interrupted
case _ : Throwable => // Exception thrown by actor system termination
}}
})}
抛出异常,JVM也会终止。这意味着,你的某些州可能还没有得到保存或其他什么。您可能希望在那里处理这些异常,因为再次,Await.ready
方法完成后,JVM将会死亡。