“关闭封闭范围/类”是什么意思?

时间:2014-11-13 05:30:57

标签: closures akka

Akka文档记录了使用Props

的危险变体
// NOT RECOMMENDED within another actor:
// encourages to close over enclosing class
val props7 = Props(new MyActor)

然后继续说明:

  

建议不要在其他actor中使用此方法,因为   它鼓励关闭封闭的范围,导致   不可序列化的道具和可能的竞争条件(打破了   演员封装)。

有人可以解释"关闭封闭范围的含义"?一直在寻找,一无所获。感谢。

2 个答案:

答案 0 :(得分:17)

在这个例子中看到,new Actor作为所谓的“按名称”参数传入,这有点棘手。可以把它想象成变成() => Actor类型的函数。每次重启时由其主管(重新)创建actor,都会调用此函数。

问题是这个函数是一个“闭包”(很容易谷歌;)),这意味着它捕获并记住它所需的周围范围内的所有东西(有时,但很少被称为“堆栈翻录”) )。 E.g val f = (a: Int) => a + xx来自哪里?它来自周围的范围。分配给f的函数litetal称为“开放术语”。在运行时,函数文字成为一个函数值(这是一种说“对象”的奇特方式),当执行关闭开放术语时,同时捕获周围范围内的所有内容。这就是“封闭”这个名字的来源。

闭包是非常有用的,但你必须小心你所关闭的。有时xdef或上帝禁止var,这导致f的结果无法预测,因为您无法控制f的时间将被调用/执行。试试吧!

阿卡的两个非常常见的反模式是:

  1. 创建Actor时关闭(外部)this引用 来自内心阶级。
  2. 在回复时关闭def sender     带有未来的信息。
  3. 我故意向谷歌发了一堆奇特的条款,顺便说一下;)

    欢呼和快乐的编码

答案 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