我发现自己经常使用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的特性并且之前也使用过它,但在某些情况下它似乎太多了。
维持简单状态的推荐方法是什么?还有其他我不知道的替代方案吗?
另外,如果我发现自己经常需要可变变量,这通常是一个不好的迹象吗?我没有正确使用演员模型吗?
答案 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将我的投票用于任何比琐碎更复杂的阴影。