如何在Akka Actor对象字段中存储数据?

kmpatx3s  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(128)

如何在Actor对象中使用可变Map来根据消息存储值?我的代码

object TestActor {
   final case class Command()
   private val mmap: mutable.Map[Int,Map[Int,Int]] = mutable.Map[Int,Map[Int,Int]]()

   def apply(): Behavior[Command] = Behaviors.receive {
       case (context, Command()) => 
            mmap += (1 -> (2 -> 3)) 
            context.log.info(nmap)
   }
}

由于mmap是scala对象中的一个静态字段,因此这会导致一些问题。因此,当多个线程向map中添加一些值时,会产生奇怪的值。由于我仍然需要使用类型化的akka角色,有没有办法让对象中有一个字段(或者以其他方式)使我仍然可以使用对象来表示使用akka.typed的参与者,并且仍然具有在TestActor参与者之间不共享的字段?

jmp7cifd

jmp7cifd1#

在Akka Typed的函数API(本示例使用的)中,执行此操作的典型方法如下:

object TestActor {
  final case class Command()

  def apply(): Behavior[Command] =
    fromMap(mutable.Map.empty)

  private def fromMap(mmap: mutable.Map[Int, Map[Int, Int]]): Behavior[Command] =
    Behaviors.receive {
      case (context, Command()) =>
        mmap += (1 -> Map(2 -> 3))
        context.log.info(mmap)
        Behaviors.same
    }
}

在这里,object基本上只是作为一个模块,该对象的字段最好被认为是全局变量。
请注意,还有一个面向对象的API用于定义类型化参与者,在Scala中为:

object TestActor {
  final case class Command()

  def apply(): Behavior[TestActor.Command] =
    Behaviors.setup { context =>
      new TestActor(context)
    }
}

class TestActor(context: ActorContext[TestActor.Command]) extends AbstractBehavior[TestActor.Command](context) {
  val mmap: mutable.Map[Int, Map[Int, Int]] = mutable.Map.empty

  def onMessage(msg: TestActor.Command): Behavior[TestActor.Command] = {
    mmap += (1 -> Map(2, 3))
    context.log.info(mmap)
    this
  }
}

值得注意的是,在Akka中,var的不可变数据(即保存不可变值的可变容器)通常比val的可变数据(即保存可变值的不可变容器)更好,因为这可以为参与者之外的东西(包括另一个参与者)提供一个通道,以“从参与者下面拔出地毯”。
在函数API中,这通常采用如下形式:

object TestActor {
  final case class Command()

  def apply(): Behavior[Command] =
    fromMap(Map.empty)

  private def fromMap(map: Map[Int, Map[Int, Int]]): Behavior[Command] =
    Behaviors.receive {
      case (context, Command()) =>
        val nextMap = map + (1 -> Map(2 -> 3))
        context.log.info(nextMap)
        withMap(nextMap)
    }
}

在面向对象的Scala API中:

// TestActor companion object is as before

class TestActor(context: ActorContext[TestActor.Command]) extends AbstractBehavior[TestActor.Command](context) {
  var map: Map[Int, Map[Int, Int]] = Map.empty

  def onMessage(msg: TestActor.Command): Behavior[TestActor.Command] = {
    map = map + (1 -> Map(2 -> 3))
    context.log.info(map)
    this
  }
}

相关问题