重启事件
在actor的生命周期内,supervisor可能会重启actor。 而且这可能不止发生一次,这取决于出错的次数。 这个事件比启动和停止要复杂的多。 这是因为一个actor的实例会被替换。

重启时,被销毁actor的preRestart方法会被调用。 在这个方法中,被销毁actor可以在被替换之前存储当前状态。
    override def preRestart(reason: Throwable, // 1
                message: Option[Any]) {  // 2
        println("preRestart")
        super.preRestart(reason, message)  // 3
    }
1.  由actor抛出的异常
2.  发生错误时,actor的receive方法正在处理的消息
3.  调用超类的方法
重写此方法一定要小心。 preRestart的默认实现是停止所有子actor,然后调用postStop方法。 如果你忘记调用超类的preRestart方法,默认行为不会发生。 请记住actor是由Props实例创建的。 Props实例调用actor的构造函数。 actor可以在构造函数中创建子actor。 当父actor重启时,如果子actor没有被销毁,就会导致越来越多的子actor。
一定要注意,重启事件中停止损坏的actor的流程跟停止事件的流程不同。 它可以监控actor的死亡,我们稍后再说。 重启损坏的actor如果不引起损坏actor发送崩溃消息,就把原来损坏actor的引用连接到新的实例上。 而停止流程中,停止损坏actor后,就把引用连接到deadLetters。 它们的共同点就是都调用postStop函数。
preRestart方法有两个参数: 重启的原因和actor损坏时正在处理的消息。 supervisor决定存储什么信息,用于重启。 当然不能用局部变量,因为重启一个新的实例后,需要继续处理。 保存损坏actor信息的一个方案是由supervisor发送消息给actor的引用(进入actor的邮箱)。 其他方式,可以写到数据库或者文件。 这完全取决于你的系统和actor的行为。
我们回到日志处理的例子, 当dbWriter崩溃时,我们不想丢失我们正在处理的消息。 解决方案是把失败的消息发送给自己的引用,这样就可以被新的实例处理了。 要注意,这种方法是发送一个消息到邮箱,邮箱中消息的顺序被改变了。 失败的消息被放在了邮箱的顶部,必须等待其他消息被处理完,才能被处理。 在例子中,这可能不是问题,但一定要记住这一点。
preRestart(译者注:原著是preStart,应该是笔误)被调用后,一个新的actor实例被创建, 因此actor的构造函数被执行。 之后新实例的postRestart钩子函数被调用。
    override def postRestart(reason: Throwable) { // 1
        println("postRestart")
        super.postRestart(reason) // 2
    }
1.  actor抛出的异常。
2.  调用超类的postRestart。
在这里,我们先给个警告。 超类的postRestart会被调用,它的默认操作是调用preStart。 超类的postRestart可以被省略,如果你确定重启时不用调用preStart,而且大多数时候是省略的。 preStart和postStop默认在重启和启动、停止事件中都会被调用,所以重写这两处的代码进行初始化和资源清理真是一石二鸟。
reason参数跟preRestart方法中一样。 重写此钩子函数,actor可以恢复到最近的正确状态,例如用在preRestart中存储的信息。