【问题标题】:Ask an actor and let him respond when he reaches a particular state in Akka 2询问演员并让他在 Akka 2 中达到特定状态时做出回应
【发布时间】:2013-10-15 13:48:03
【问题描述】:

我对 Akka 很陌生,所以我的问题可能看起来很简单:

我有一个叫workerA 的演员,它使用FSM,因此可以处于FinishedComputing 这两种状态:

sealed trait State
case object Finished extends State
case object Computing extends State

sealed trait Data
case object Uninitialized extends Data
case class Todo(target: ActorRef, queue: immutable.Seq[Any]) extends Data

workerA 接收到GetResponse 时,它应该回答它是否处于状态Finished

这样做的正确方法是什么?我知道我们应该避免在这种范式中被阻塞,但这里只关注顶级参与者。 谢谢

【问题讨论】:

  • 看起来很简单,或者我不懂问题。非Finished状态应该怎么办
  • 当没有处于 Finished 状态时,actor 会从其他不同的 actor 收集信息,以便创建要发送给 GetResponse 发送者的结果。即使您认为它很简单,也要给出您的答案。thx

标签: scala akka actor


【解决方案1】:

我不一定确定您是否需要 FSM。当您有许多状态以及这些状态之间的许多可能(并且可能很复杂)的状态转换时,FSM 是一个非常好的工具。就您而言,如果我理解正确,您基本上有两种状态;收集数据并完成。似乎也只有一个状态转换,从gathering -> finished 开始。如果这一切都正确,那么我建议您只需使用become 来解决您的问题。

我在下面有一些代码来展示我所描述的一个简单的例子。基本思想是主角将一些工作分给一些工人,然后等待结果。如果有人在工作完成时询问结果,演员会隐藏该请求,直到工作完成。完成后,演员将回复任何要求结果的人。代码如下:

case object GetResults
case class Results(ints:List[Int])
case object DoWork

class MainActor extends Actor with Stash{
  import context._

  override def preStart = {
    val a = actorOf(Props[WorkerA], "worker-a")
    val b = actorOf(Props[WorkerB], "worker-b")
    a ! DoWork
    b ! DoWork
  }

  def receive = gathering(Nil, 2)

  def gathering(ints:List[Int], count:Int):Receive = {
    case GetResults => stash()
    case Results(i) =>      
      val results = i ::: ints
      val newCount = count - 1
      if (newCount == 0){
        unstashAll()
        become(finished(results))        
        child("worker-a") foreach (stop(_))
        child("worker-b") foreach (stop(_))
      }
      else
        become(gathering(results, newCount))
  } 

  def finished(results:List[Int]):Receive = {
    case GetResults => sender ! results
  }
}

class WorkerA extends Actor{
  def receive = {
    case DoWork =>

      //Only sleeping to simulate work.  Not a good idea in real code
      Thread sleep 3000
      val ints = for(i <- 2 until 100 by 2) yield i
      sender ! Results(ints.toList)
  }
}

class WorkerB extends Actor{
  def receive = {
    case DoWork =>

      //Only sleeping to simulate work.  Not a good idea in real code
      Thread sleep 2000  
      val ints = for(i <- 1 until 100 by 2) yield i
      sender ! Results(ints.toList)      
  }
}

那么你可以如下测试:

val mainActor = system.actorOf(Props[MainActor])
val fut = mainActor ? GetResults
fut onComplete (println(_))

【讨论】:

    【解决方案2】:

    您可以对 FSM 状态进行模式匹配:

    // insert pattern matching stuff instead of ...
    
    class MyActor extends Actor with FSM[State, Message] {
      startWith(Finished, WaitMessage(null))
    
      when(Finished) {
        case Event(Todo(... =>
          // work
          goto(Computing) using Todo(...)
        case Event(GetResponse(... =>
          // reply: sender ! msg // or similar
      }
    
      /* the rest is optional. You can use onTransition below to send yourself a message to    report status of the job: */
      when(Busy) {
        case Event(Finished(... =>
          // reply to someone: sender ! msg // or similar
          goto(Finished)
      }
    
      onTransition {
        case Finished -> Computing =>
          // I prefer to run stuff here in a future, and then send a message to myself to signal the end of the job:
          self ! Finished(data)
      }
    

    更具体地解决问题的编辑:

    class MyActor extends Actor with FSM[State, Message] {
      startWith(Finished, WaitMessage(null))
    
      when(Finished) {
        case Event(Todo(... =>
          // work
          goto(Computing) using Todo(...)
        case Event(GetResponse(... =>
          // reply: sender ! msg // or similar
          stay
      }
    
      initialize()
    }
    

    【讨论】:

    • 是的,但是如果 MyActor 在忙碌时收到 GetResponse 会发生什么?
    • 接下来会发生什么取决于您的要求。您可以在进入 Finished 状态之前忽略 GetResponse,或者您可以使用 Stash 特征来推迟对 GetResponse 消息的处理。在任何情况下,稍微更具体的问题都会有所帮助(即:你想做什么)。
    • @Mermoz 如果您不处理处于特定状态的特定消息,它将传递给 whenUnhandled {} 块,在您的情况下将被忽略。在此处查看文档:doc.akka.io/docs/akka/snapshot/scala/fsm.html.
    • @Endre Varga:谢谢stash 是我想要的! @A I fgfgf 感谢您提供的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 2014-07-20
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    相关资源
    最近更新 更多