构造函数与 preStart:何时使用哪个?
Posted
技术标签:
【中文标题】构造函数与 preStart:何时使用哪个?【英文标题】:Constructor vs. preStart: when to use which? 【发布时间】:2018-07-26 12:05:53 【问题描述】:在 Akka 中,您可以在构造函数中初始化 actor 的状态。此外,作为参与者生命周期的一部分,preStart
方法可以被重写以初始化参与者的状态并被调用:
postRestart
被覆盖不调用它
这两种方式(构造函数和preStart
)似乎涵盖了参与者启动阶段的重叠阶段,略有不同的是构造函数保证在重新启动时被调用,而preStart
可以跳过,前提是您覆盖 postRestart
。
关于在哪种情况下使用哪一种,是否有公认的或记录在案的最佳实践或模式?
【问题讨论】:
【参考方案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 的列表的?以上是关于构造函数与 preStart:何时使用哪个?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我们需要复制构造函数以及何时应该在 java 中使用复制构造函数
何时使用 TestFixtureSetUp 属性而不是默认构造函数?