Akka 上下文成为维护状态顺序

Akka context become preserving state order

我有以下简单的 Actor:

class MutableStateActor extends Actor with ActorLogging {

  var counter = 0

  val increment = (x: Int) => {
    counter = counter + 1
    s"$counter"
  }

  def receive = {
    case _ => context.become(mutableReceiver)
  }

  def mutableReceiver: Receive = {
    case Increment => {
      Future { println(s"counter in Increment is ${increment(counter)}"); self ! CounterStatus }
      //println(s"counter in Increment is ${increment(counter)}"); self ! CounterStatus
    }
    case CounterStatus => {
      println(counter)
    }
  }
}
object MutableStateActor {
  case class Increment()
  case class CounterStatus()
}

当我使用以下测试对其进行测试时:

  "A MutableStateActor" must {

    val actorRef = system.actorOf(Props[MutableStateActor])

    "mutate state in order" in {
      1 to 5 foreach {
        x => actorRef ! Increment
      }
    }
  }

我可以看到计数器递增的顺序被保留了下来。我得到:

counter in Increment is 1
counter in Increment is 2
counter in Increment is 3
counter in Increment is 4
4
4
4
4

如果我如下更改 actor 中的接收方法而不执行 context.become:

 def receive: Receive = {
    case Increment => {
      Future { println(s"counter in Increment is ${increment(counter)}"); self ! CounterStatus }
      //println(s"counter in Increment is ${increment(counter)}"); self ! CounterStatus
    }
    case CounterStatus => {
      println(counter)
    }
  }

我得到了关于计数器增量的非确定性行为。

counter in Increment is 2
counter in Increment is 4
counter in Increment is 1
counter in Increment is 3
counter in Increment is 5
5
5
5
5
5

在第一种情况下,printlnFuture被解析时执行,它们是按照创建的顺序被解析的。

第二种情况,println在一个线程中执行,然后return一个Future,因此,线程执行的顺序是不确定的。