无法在 Akka Actor 的 receive() 中增加 'total' 变量

cannot increment a 'total' variable inside receive() in Akka Actor

我是 Scala 的新手(Akka Actors。我知道避免 actors 中的可变状态有好处,但是我找到了增加 var 总数的解决方案 类似于 SO 问题给出的问题:

Alternatives to using "var" for state with actors?

我的代码如下。

解决方案看起来很简单:我的 Calculator actor 维护一个本地 var 总计,并且在 receive() 中对案例 class 的适当匹配 => 使用从匹配案例中提取的金额来增加这个总计 class.

我的案例陈述有效。 println 显示每次我的输入与 case 语句匹配时,要添加到总数 (amt) 的金额由匹配产生。 IE。这按预期工作:

case MyCaseClass(_, amt) => println(amt)

但是这一行:

案例 MyCaseClass(_, amt) => 总计 += amt

失败。本地 var total 永远不会递增。我尝试使用列表,并将新的 amt 作为新成员添加到 var 列表中,但这也失败了。在每种情况下,局部变量的增量,无论是类型 Double 还是 List[Double] 都会失败。为什么是这样?我该怎么做才能让增量在 receive() 中工作?

代码:

import akka.actor.ActorSystem
import akka.actor.Props

class CostingActor extends Actor {
  var bedrooms:Double = 0.0
  var bathrooms: Double = 0.0

  def receive = {
    //THIS IS THE OFFENDING LINE OF CODE--PRINTS OUT P FINE, EACH TIME A MATCH IS MADE
    case RoomPojo("Bedroom", p) => bedrooms += p    //println(p)
    case RoomPojo("Bathroom", p) => bathrooms += p  //println(p)
    case "total" => println(bedrooms + bathrooms)
  }
}

object Main extends App {
  val system = ActorSystem("CostingSystem")
  var costingActor = system.actorOf(Props[CostingActor], name =     "costingactor")
  var roomActor = system.actorOf(Props[RoomActor], name = "roomactor")
  for (i <- 0 until args.length)
    roomActor ! args(i)
  //the following line of code may be wrong; (I also tried a future) but should n't the variables bedrooms
  // and bathrooms still show at least some incrementation?
    costingActor ! "total"

    system.shutdown()
}



object RoomActor {
  case class RoomPojo(name:String, price:Double) {}

}

class RoomActor extends Actor {

  val checkout = context.actorOf(Props[CostingActor])
  def receive: Receive = {
    case "Bedroom"  => checkout ! new RoomPojo("Bedroom", 45.0)
    case "Bathroom" => checkout ! new RoomPojo("Bathroom", 90.0)
    case _ => println("missed in room")
  }
}

您的 Main 中的 system.actorOf(Props[CostingActor], name = "costingactor")RoomActor 中的 context.actorOf(Props[CostingActor]) 是不同的演员。每个 actorOf 创建该 actor 的一个新实例,每个都有自己的状态。您将 RoomPojo 消息发送到一个 actor 实例,并向一个完全不同的实例请求状态,该实例根本没有看到任何 RoomPojo 消息。

您可以修改 RoomActor 以将 actorRef 作为参数并将 costingActor 传递给 Props,这样您就可以为状态使用相同的 actor 实例。

var costingActor = system.actorOf(Props[CostingActor], name = "costingactor")
var roomActor = system.actorOf(Props(classOf[RoomActor], costingActor), name = "roomactor")

// ...

class RoomActor(checkout: ActorRef) extends Actor

此外,由于一切都是异步的,如果您在发送消息后立即关闭系统,'total'消息可能会丢失。