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