我很擅长使用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)
}
}
状态在第二个版本中以哪个成为例子?
答案 0 :(得分:5)
从概念上讲,状态在执行堆栈上。 Receive
是PartialFunction
的类型别名。 start
方法实现中的部分函数将关闭lst
参数。然后,可以使用执行上下文中的参数值按需评估接收行为。
因此,每次调用start方法时,lst
的大小确实会增长。
关于泄漏内存,请注意默认情况下become
未被禁用,因此没有内存泄漏。只有当您为false
参数传递discardOld
时,允许将来unbecome
,才会出现内存泄漏问题。
答案 1 :(得分:4)
该州由Akka机械公司持有。有一堆receive
"块"
每次拨打become
或unbecome
时都会发生变异。
堆栈表示为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
通常用于初始化或状态的临时更改,例如流控制。