Akka文档记录了使用Props
:
// NOT RECOMMENDED within another actor:
// encourages to close over enclosing class
val props7 = Props(new MyActor)
然后继续说明:
建议不要在其他actor中使用此方法,因为 它鼓励关闭封闭的范围,导致 不可序列化的道具和可能的竞争条件(打破了 演员封装)。
有人可以解释"关闭封闭范围的含义"?一直在寻找,一无所获。感谢。
答案 0 :(得分:17)
在这个例子中看到,new Actor
作为所谓的“按名称”参数传入,这有点棘手。可以把它想象成变成() => Actor
类型的函数。每次重启时由其主管(重新)创建actor,都会调用此函数。
问题是这个函数是一个“闭包”(很容易谷歌;)),这意味着它捕获并记住它所需的周围范围内的所有东西(有时,但很少被称为“堆栈翻录”) )。 E.g val f = (a: Int) => a + x
。 x
来自哪里?它来自周围的范围。分配给f
的函数litetal称为“开放术语”。在运行时,函数文字成为一个函数值(这是一种说“对象”的奇特方式),当执行关闭开放术语时,同时捕获周围范围内的所有内容。这就是“封闭”这个名字的来源。
闭包是非常有用的,但你必须小心你所关闭的。有时x
是def
或上帝禁止var
,这导致f
的结果无法预测,因为您无法控制f
的时间将被调用/执行。试试吧!
阿卡的两个非常常见的反模式是:
this
引用
来自内心阶级。 def sender
带有未来的信息。我故意向谷歌发了一堆奇特的条款,顺便说一下;)
欢呼和快乐的编码
答案 1 :(得分:7)
作为@ agilesteel的正确答案的补充,一些参考文献:
解释什么是闭包: Scala编程,8.7,闭包
解释闭包可能导致序列化问题的原因:SIP-21 - Spores
这是一个代码示例,根据SIP-21中的示例创建一个不可序列化的Props对象,因为关闭了一个不可序列化的对象:
case class Helper(name: String)
object MyNonserializableObject {
val helper = Helper("the helper")
val props7 = Props(new MyActor(helper))
}
尽管helper
本身是可序列化的,但是新的MyActor(帮助者)"按名称传递,因此捕获this.helper
,而this
不可序列化。
您可以看到,参数是Props
apply
方法的签名中的名称传递的,其中creator
参数中有⇒:
def apply[T <: Actor](creator: ⇒ T)(implicit arg0: ClassTag[T]): Props