【问题标题】:Constructor vs. preStart: when to use which?构造函数与 preStart:何时使用哪个?
【发布时间】:2018-07-26 12:05:53
【问题描述】:

在 Akka 中,您可以在构造函数中初始化 actor 的状态。此外,作为参与者生命周期的一部分,preStart 方法可以被重写以初始化参与者的状态并被调用:

  • actor 首次启动时,在它开始处理其第一条消息之前
  • 当actor重新启动时,除非postRestart被覆盖不调用它

这两种方式(构造函数和preStart)似乎涵盖了参与者启动阶段的重叠阶段,略有不同的是构造函数保证在重新启动时被调用,而preStart可以跳过,前提是您覆盖 postRestart

关于在哪种情况下使用哪一种,是否有公认的或记录在案的最佳实践或模式?

【问题讨论】:

    标签: akka


    【解决方案1】:

    来自initialization via constructor上的文档:

    使用构造函数进行初始化有很多好处。首先,它可以使用val 字段来存储任何在actor实例生命周期内不会改变的状态,从而使actor的实现更加健壮。构造函数在创建调用 actorOf 的 Actor 实例时调用,并且在重新启动时也会调用,因此 Actor 的内部总是可以假设发生了正确的初始化。

    来自initialization via preStart上的文档:

    actor 的方法preStart() 只在第一个实例的初始化期间直接调用一次,即在创建其ActorRef 时。在重启的情况下,preStart() 会从 postRestart() 调用,因此如果没有被覆盖,preStart() 会在每次重启时被调用。但是,通过覆盖 postRestart() 可以禁用此行为,并确保只有一次调用 preStart()

    此模式的一个有用用法是在重新启动期间禁止为子级创建新的ActorRefs。这可以通过覆盖preRestart() 来实现。

    如果您希望每次实例化actor时都进行初始化(包括重新启动:在重新启动时,会创建底层actor的新实例),请通过构造函数使用初始化。这方面的示例场景是在创建角色时使用不变状态。

    如果您希望仅在创建 Actor 的第一个实例时进行初始化,请通过 preStart 使用初始化并覆盖 postRestart 以不调用 preStart。示例用例是在重新启动时保留子 Actor(默认情况下,preRestart 会停止 Actor 的子代,这就是文档提到此示例用例覆盖 preRestart 的原因)。

    【讨论】:

    • 哈,在问之前我还没有深入了解文档。谢谢!
    • 首先,谢谢你的好回答:-) 但是我还有一个问题。假设我使用不停止子代的方法以不触发新 ActorRefs 的生成。重启后actor如何知道孩子的ActorRefs?重新启动的参与者是从头开始创建的,没有旧停止实例的任何状态。它是如何计算出孩子的 ActorRefs 的列表的?
    猜你喜欢
    • 2011-06-26
    • 1970-01-01
    • 2013-11-30
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多