Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 为什么我应该使用context.been()在Actor中存储内部状态?_Scala_Akka_Actor - Fatal编程技术网

Scala 为什么我应该使用context.been()在Actor中存储内部状态?

Scala 为什么我应该使用context.been()在Actor中存储内部状态?,scala,akka,actor,Scala,Akka,Actor,我读过一篇文章,有一个问题是关于“5.2.应该只根据上下文改变演员的状态。变成”。我不明白为什么使用var存储内部状态是如此糟糕。如果actor按顺序执行所有消息,我就看不到任何问题的根源。我遗漏了什么?请考虑您引用的中的第一个示例: class MyActor extends Actor { val isInSet = mutable.Set.empty[String] def receive = { case Add(key) => isInSet +=

我读过一篇文章,有一个问题是关于“5.2.应该只根据上下文改变演员的状态。变成”。我不明白为什么使用
var
存储内部状态是如此糟糕。如果actor按顺序执行所有消息,我就看不到任何问题的根源。我遗漏了什么?

请考虑您引用的中的第一个示例:

class MyActor extends Actor {
  val isInSet = mutable.Set.empty[String]

  def receive = {
    case Add(key) =>
      isInSet += key

    case Contains(key) =>
      sender() ! isInSet(key)
  }
}
这个例子本身没有什么不正确的地方,所以你没有遗漏一些重要的理解。如您所知,参与者按顺序处理其邮箱中的消息,因此在内部变量中表示其状态并更改此状态是安全的,只要参与者不公开该状态1

been
通常用于动态切换参与者的行为(例如,更改参与者处理的消息类型)和/或其状态。在本文的第二个示例中,参与者的状态作为参数编码在其行为中。这是第一个示例的一个优雅的替代方案,但在这个简单的例子中,这是一个偏好问题

然而,
变为
的一个场景确实可以大放异彩,那就是有许多状态转换的参与者。如果不使用
been
,参与者在其
receive
块中的逻辑可能会变得非常庞大,或者变成
if-else
语句的丛林。作为使用
been
对状态转换建模的一个示例,请查看这个问题建模的例子



1潜在的问题是,
isInSet
是一个
val
,它是一个可变的
集,因此,如果参与者将此状态暴露给参与者自身之外的某个对象(在本例中没有这样做),可能会发生奇怪的事情。例如,如果参与者在消息中将此
Set
发送给另一参与者,则外部参与者可以更改此状态,从而导致意外的行为或竞争条件。通过将
val
更改为
var
,将可变集更改为不可变
Set
,我认为在actors中使用
var
不一定有什么问题,原因正是您提到的(请记住,这仅适用于在
接收(…)
上下文中执行的代码,即,如果您启动线程,或使用
未来的
,即使它来自
接收
,该代码也不再按顺序执行)

但是,我个人更喜欢使用
context.been(…)
来控制状态,主要是因为它清楚地向我显示了参与者中可以更改的状态(
var
s可以分散在各个地方)

我还更喜欢将它限制为0或1次调用
context.been(…)
每个处理的消息,这样就可以清楚地知道这种状态转换发生在哪里


也就是说,通过使用一种约定,您可以在一个地方定义所有的
var
s,并确保在消息处理中将它们重新分配到一个地方(比如在末尾)。

我开始学习scala,这个答案不仅是最简洁的,而且是最完整的+1您的意思是什么“即使它来自接收”?对不起,我的意思是“即使它来自接收内部”。我的意思是,如果在接收函数内部,如果您要执行类似于
Future{someMutableNumber+=1}
someMutableNumber
的操作,将不再按顺序访问,并且将受到竞争条件的限制。