使用“var”作为演员的状态的替代方案?

时间:2013-09-15 01:47:01

标签: scala akka actor

我发现自己经常使用vars与akka演员来维持状态。例如,如果我的演员需要维护一个项目列表,我可能会这样做:

class ListActor extends Actor{
  var xs : List[Int] = List()

  def receive = {
    case x : Int => xs = x :: xs
  }
}

使用可变变量似乎违背了Scala的精神。或者我用过这个:

class ListActor2 extends Actor{
  import context._

  def collect_ints(accu : List[Int]) : Receive = {
    case x : Int => become(collect_ints(x :: accu))
  }

  def receive = collect_ints(Nil)
}

我喜欢这看起来更多,但我是否要担心堆栈溢出?

我知道FSM的特性并且之前也使用过它,但在某些情况下它似乎太多了。

维持简单状态的推荐方法是什么?还有其他我不知道的替代方案吗?

另外,如果我发现自己经常需要可变变量,这通常是一个不好的迹象吗?我没有正确使用演员模型吗?

3 个答案:

答案 0 :(得分:20)

我没有看到var对于actor模型中的简单状态有任何问题。

根据设计,Akka通过并发访问状态变量来防止actor被破坏或锁定的状态。

只要您没有使用Future for instance将状态暴露给其他线程,使用var进行简单状态应该不是问题。

答案 1 :(得分:7)

become方法有两种变体:一种将行为推送到堆栈,另一种不推送。后者是默认值,因此您不必担心行为堆栈变得太大。使用become以这种方式管理状态是完全有效的用途。

答案 2 :(得分:4)

Akka FSM实际上是一个非常紧凑的习惯用法,用于在演员系统中维护状态,如下例所示:

sealed trait State
case object Active extends State

class ListActor extends Actor with FSM[State,List[Int]] {

  startWith(Active,List[Int]())

  when(Active) {
    case Event(x:Int,xs) => stay using x :: xs
  }
}

在使用了这里讨论的所有替代方案之后,FSM将我的投票用于任何比琐碎更复杂的阴影。