是否可以在演员中使用Akka调度程序?

Fel*_*ers 28 scala scheduler akka

我希望有可能让演员入睡一会儿.演员应该决定自己要睡多久.由于Thread.sleep()不是推荐的方法,我想在akka中使用调度程序.因此我定义了一个演员是另一个演员可以注册被唤醒.

class Scheduler extends Actor {

  def receive = {
    case Sleep(duration) => context.system.scheduler.scheduleOnce(duration) {
      sender ! Ring
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但发送方从不接收Ring消息.所以我的问题是

  • 是否在演员内部推荐了调度程序?
  • 为什么发送方从不接收Ring消息?
  • 如果这不可能,那么解决问题的推荐方法是什么?

Rol*_*uhn 44

让我首先回答标题问题:是的,可以在actor中使用调度程序.

case Sleep(duration) =>
  context.system.scheduler.scheduleOnce(duration, self, Ring)
Run Code Online (Sandbox Code Playgroud)

现在回答问题背后的问题

你没有说出你真正想要实现的目标,所以我在这里做了一个有根据的猜测,你想让演员通常做一些叫做"X"的事情 - 做一段叫做"Y"的事情,暂停"X" "活动.完整的解决方案是

class Sleepy extends Actor {
  def receive = {

    ... // cases doing “X”

    case Sleep(duration) =>
      case object WakeUp
      context.system.scheduler.scheduleOnce(duration, self, WakeUp)
      context.become({
        case WakeUp => context.unbecome()
        // drop the rest
      }, discardOld = false)
  }
}
Run Code Online (Sandbox Code Playgroud)

使用FSM特性并在正常状态和睡眠状态之间切换也可以实现相同的效果.当然,你可以在睡觉时做任何你想做的事情,例如混合StashAkka 2.1 中的特性,并stash()在睡觉时,unstashAll()在收到WakeUp消息时呼叫所有(或一些)消息; 或者你可以完全做其他事情.演员非常灵活.

演员不做什么

演员从不真正睡觉,他们总是处理传入的消息.如上所示,您可以定义这意味着什么,但基本原则是您不能挂起actor,以便它不会处理其邮箱中的消息.


Rya*_*pte 16

您正在关闭传递给调度程序的闭包中的"sender".这意味着Ring消息很可能被发送给错误的actor.你应该这样做:

case Sleep(duration) => 
  val s = sender
  context.system.scheduler.scheduleOnce(duration) {
    s ! Ring
  }
}
Run Code Online (Sandbox Code Playgroud)