Scala Akka演员避免突变状态

Scala Akka演员避免突变状态,scala,akka,Scala,Akka,我对使用Akka演员很陌生。最近,我读到了关于分布式参与者或远程参与者(不管你怎么称呼它)的文章。到目前为止,我在Actor中使用state,并在receive方法中对其进行变异,这让我感到很舒服。快乐的日子!现在我想在几个JVM中分发我的actor,我已经看到我的actor中的状态可能是一个问题 我确实读过关于“变成”和“不合身”的书,我只是想知道阿克卡是如何在内部处理这个问题的 与国家: class TestActor extends Actor { var state = List.e

我对使用Akka演员很陌生。最近,我读到了关于分布式参与者或远程参与者(不管你怎么称呼它)的文章。到目前为止,我在Actor中使用state,并在receive方法中对其进行变异,这让我感到很舒服。快乐的日子!现在我想在几个JVM中分发我的actor,我已经看到我的actor中的状态可能是一个问题

我确实读过关于“变成”和“不合身”的书,我只是想知道阿克卡是如何在内部处理这个问题的

与国家:

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)
  }
}

第二个版本中的“变成”示例的状态在哪里?

使用
been
/
unbecome
时,您只是在更改参与者的行为,而不是状态。国家保持不变。但是,当使用它时,您可能会泄漏内存(查看此示例了解更多详细信息:)

还有一点值得一提的是,如果您的参与者被主管重新启动,它将从其原始行为开始


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

当使用
been
/
unbecome
时,您只是在更改参与者的行为,而不是状态。国家保持不变。但是,当使用它时,您可能会泄漏内存(查看此示例了解更多详细信息:)

还有一点值得一提的是,如果您的参与者被主管重新启动,它将从其原始行为开始


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

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

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


关于内存泄漏,请注意默认情况下
been
是不需要的,因此没有内存泄漏。只有在为
discardoold
参数传递
false
时,考虑到将来的
取消编译
,才会出现内存泄漏问题。

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

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


关于内存泄漏,请注意默认情况下
been
是不需要的,因此没有内存泄漏。只有将
discardoold
参数的
false
传递,并考虑到未来的
unbecome
,才会出现内存泄漏问题。

该状态由Akka机器保持。有一堆
receive
“块” 每次调用
变为
不符合
时,它都会发生变异

堆栈表示为

有两个地方可以替换
列表

与Erlang相比,Akka不能使用递归调用创建的执行堆栈来编码状态,因为这意味着阻塞调用。Akka无法承受任何线程上的阻塞调用,因此它需要一个
var


Akka的
receive
可能会给人一种递归调用的错觉,但请记住,
receive
块返回一个
PartialFunction
函数,调用该函数时,调用
start
,状态由Akka机器保持。有一堆
receive
“块” 每次调用
变为
不符合
时,它都会发生变异

堆栈表示为

有两个地方可以替换
列表

与Erlang相比,Akka不能使用递归调用创建的执行堆栈来编码状态,因为这意味着阻塞调用。Akka无法承受任何线程上的阻塞调用,因此它需要一个
var


Akka的
receive
blocks可能会给人一种递归调用的错觉,但是请记住,
receive
块返回一个
PartialFunction
,当调用该函数时,调用
start

,但第二个版本中的状态在哪里。TestActor中没有var?使用Add message调用start 3次后,start方法的参数lst的大小是否为3?但第二个版本中的状态在哪里。TestActor中没有var?使用Add message调用start 3次后,start方法的参数lst的大小是否为3?这有点不准确。1. <代码>变为
不会关闭任何内容。2.
Been
的参数不是按名称,在执行
Been
调用之前执行
start
方法。“按名称”错觉是因为
start
返回一个
PartialFunction
。对,因此它返回一个
PartialFunction
这一事实意味着返回的是函数本身,而不是函数的求值。所以从技术上讲,它是通过函数本身的值(作为值)传递的,而不是通过名称传递的。这是对正在发生的事情的准确描述吗?因此,可以准确地说,
start
实现中的
PartialFunction
是在
lst
参数的当前值之上关闭的。我将使用这些评论中的进一步澄清改写答案。是的,retu