阿卡演员避免变异状态

时间:2015-01-20 15:52:48

标签: scala akka

我很擅长使用Akka演员。最近,我读到了分布式演员或远程演员(无论你怎么称呼它)。到目前为止,我一直很舒服地使用我的Actor中的状态并在我的接收方法中改变它。快乐的时光!现在我想把我的演员分配到几个JVM上,我已经看到我演员中的状态可能是一个问题。

我确实读过关于成为和不成功的内容,我只是想知道Akka如何在内部处理这个问题?

状态:

class TestActor extends Actor {
  var state = List.empty[String])

  def receive = 
    case Add(elem) => state + elem
    case Contains(elem) => sender() ! state.contains(elem)
  }
}

删除状态:

class TestActor extends Actor {
  def receive = start(List.empty[String])

  def start(lst: List[String]): Receive = {
    case Add(elem) =>
      context become start(lst+ elem)

    case Contains(elem) =>
      sender() ! lst.contains(elem)
  }
}

状态在第二个版本中以哪个成为例子?

3 个答案:

答案 0 :(得分:5)

从概念上讲,状态在执行堆栈上。 ReceivePartialFunction的类型别名。 start方法实现中的部分函数将关闭lst参数。然后,可以使用执行上下文中的参数值按需评估接收行为。

因此,每次调用start方法时,lst的大小确实会增长。

关于泄漏内存,请注意默认情况下become未被禁用,因此没有内存泄漏。只有当您为false参数传递discardOld时,允许将来unbecome,才会出现内存泄漏问题。

答案 1 :(得分:4)

该州由Akka机械公司持有。有一堆receive"块" 每次拨打becomeunbecome时都会发生变异。

堆栈表示为an immutable List bound to a var

有两个地方替换了List

与Erlang相比,Akka无法使用递归调用创建的执行堆栈来编码状态,因为这意味着阻塞调用。 Akka无法对其任何线程进行阻塞调用,因此需要var

Akka的receive阻止可能会给出递归调用的错觉,但请记住,receive阻止返回PartialFunction,当被调用时,致电start

答案 2 :(得分:2)

使用become / unbecome时,您只是改变了演员的行为,而不是状态。国家保持不变。但是,在使用它时,您可能会泄漏内存(请查看此示例以获取更多详细信息:https://github.com/akka/akka/blob/master/akka-docs/rst/scala/code/docs/actor/UnnestedReceives.scala

值得一提的另一件事是,如果你的演员被主管重新启动,它将以其原始行为开始。

become/unbecome通常用于初始化或状态的临时更改,例如流控制。