【问题标题】:cannot increment a 'total' variable inside receive() in Akka Actor无法在 Akka Actor 中的 receive() 中增加“总”变量
【发布时间】:2023-03-03 12:00:04
【问题描述】:

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

Alternatives to using "var" for state with actors?

我的代码如下。

解决方案看起来很简单:我的 Calculator actor 维护一个本地 var 总计,并且在 receive() => 中的案例类上的适当匹配将这个总计增加一个从匹配案例类中提取的数量。

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

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

但是这一行:

case 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")
  }
}

【问题讨论】:

  • 你能粘贴你的代码吗?
  • 在这种情况下我宁愿使用状态。
  • @curious 这是我的代码的一部分——为满足评论限制而删节:class CostingActor extends Actor { private var bedroomTotal = 0.0 var bathroomTotal = 0.0 def receive = { case RoomPojo("Bedroom", p) =&gt; bedroomTotal += p; case RoomPojo("Bathroom", p) =&gt; bathroomTotal += p; case "total" =&gt; println(bedroomTotal + bathroomTotal) } }class RoomActor extends Actor { val checkout = context.actorOf(Props[CostingActor]) def receive: Receive = { case "Bedroom" =&gt; checkout ! new RoomPojo("Bedroom", 25.0) ... } }
  • 只需编辑您的问题并将代码放入其中

标签: scala state actor mutable


【解决方案1】:

来自Mainsystem.actorOf(Props[CostingActor], name = "costingactor") 与来自RoomActorcontext.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

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

【讨论】:

  • 谢谢,knutwalker,这看起来很有帮助。我会试试这个。
猜你喜欢
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 2013-11-27
  • 1970-01-01
  • 2018-07-17
  • 2023-04-02
  • 1970-01-01
相关资源
最近更新 更多