我希望有可能让演员入睡一会儿。演员应该决定自己要睡多久。由于Thread.sleep()不是推荐的方法,我想在akka中使用调度程序。因此我定义了一个演员是另一个演员可以注册被唤醒。
class Scheduler extends Actor {
def receive = {
case Sleep(duration) => context.system.scheduler.scheduleOnce(duration) {
sender ! Ring
}
}
}
但发送方从未收到过Ring消息。 所以我的问题是
答案 0 :(得分:44)
让我先回答标题问题:是的,可以在演员中使用调度程序。
case Sleep(duration) =>
context.system.scheduler.scheduleOnce(duration, self, Ring)
你没有说出你真正想要达到的目标,所以我在这里做了一个有根据的猜测,你想让演员 - 通常做一些叫做“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)
}
}
使用FSM特性并在正常状态和睡眠状态之间切换也可以实现相同的效果。当然,你可以在睡觉时做任何你想做的事,例如混合使用Akka 2.1中的Stash
特征,并在睡眠时调用stash()
所有(或部分)消息,unstashAll()
获取WakeUp
消息时;或者你可以完全做其他事情。演员非常灵活。
演员从不真正入睡,他们总是处理传入的消息。如上所示,您可以定义这意味着什么,但基本原则是您不能挂起一个actor,以便它不会处理其邮箱中的邮件。
答案 1 :(得分:16)
您正在关闭传递给调度程序的闭包中的“sender”。这意味着Ring消息很可能被发送给错误的actor。你应该这样做:
case Sleep(duration) =>
val s = sender
context.system.scheduler.scheduleOnce(duration) {
s ! Ring
}
}
答案 2 :(得分:0)
Roland Kuhn的回答涵盖了这个主题,我只是想补充一点,使用调度程序有另一个常见的用例: 当向另一个演员发送消息并等待这个演员回应时,通常会超时等待等待。
otherActor ! Request(...)
context.system.scheduler.scheduleOnce(duration, self, WakeUp)
...
case Response(...) => ...
case WakeUp => context stop self