Akka文档记录了使用Props
:的危险变体
// NOT RECOMMENDED within another actor:
// encourages to close over enclosing class
val props7 = Props(new MyActor)
然后继续陈述:
不建议在其他参与者中使用此方法,因为它鼓励关闭封闭范围,导致不可序列化的Props和可能的竞争条件(破坏演员封装)。
有人能解释一下"封闭范围"的含义吗?到处找都找不到。谢谢
在这个例子中,new Actor
作为一个所谓的"by name"参数传入有点棘手。把它想象成一个() => Actor
类型的函数。在重新启动过程中,每当参与者的主管(重新)创建时,都会调用此函数。
问题是,这个函数是一个"闭包"(对谷歌来说很容易;),这意味着它可以捕获并记住周围范围内所需的一切(有时,但很少被称为"堆栈剥离")。例如val f = (a: Int) => a + x
。x
从哪里来?它来自周围的范围。分配给f
的函数litetal被称为"开放项"。在运行时,函数文字变成了一个函数值(这是"对象"的一种奇特说法),当执行时,它关闭了开放项,同时捕获了周围范围中的所有内容。这就是"闭包"这个名字的由来。
闭包非常有用,但你必须小心你的闭包。有时x
是def
或上帝保佑var
,这会导致f
的结果不可预测,因为您无法控制调用/执行f
的时间。试试看!
阿卡有两个非常常见的反家长主义者:
- 创建Actor时关闭(外部)
this
引用来自内部类 - 响应时关闭
def sender
带着未来的信息
顺便说一句,我故意给你谷歌提供了一堆花哨的术语。)
欢呼和快乐编码
作为@agilesteel精细答案的补充,一些参考文献:
解释闭包是什么:Scala编程,8.7,闭包
解释为什么闭包会导致序列化问题:SIP-21-孢子
下面是一个创建Props对象的代码示例,该对象由于关闭了一个不可序列化的对象而不可序列化,基于SIP-21中的示例:
case class Helper(name: String)
object MyNonserializableObject {
val helper = Helper("the helper")
val props7 = Props(new MyActor(helper))
}
尽管helper
本身是可序列化的,但"new MyActor(helper)"是按名称传递的,因此会捕获this.helper
,而this
是不可序列化的。
您可以看到actor参数是通过Props
apply
方法签名的名称传递的,其中有⇒在creator
参数中:
def apply[T <: Actor](creator: ⇒ T)(implicit arg0: ClassTag[T]): Props