俳優をしばらく寝かせる可能性が欲しいです。俳優は、どれくらいの時間寝るかを自分で決める必要があります。 Thread.sleep()はこれを行うための推奨される方法ではないため、akkaでスケジューラーを使用することを考えました。したがって、私は、別の俳優が起こされるために登録できる俳優を定義しました。
class Scheduler extends Actor {
def receive = {
case Sleep(duration) => context.system.scheduler.scheduleOnce(duration) {
sender ! Ring
}
}
}
ただし、送信側のアクターはリングメッセージを受信しません。だから私の質問は
最初にタイトルの質問に答えましょう。はい、アクター内でスケジューラーを使用することは可能です。
_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特性を使用し、通常状態とスリープ状態を切り替えることで、同じことを実装することもできます。そしてもちろん、あなたは眠っている間にあなたがやりたいことを何でもすることができます、例えば。 Akka2.1のStash
トレイトをミックスし、スリープ中にすべて(または一部)のメッセージに対してstash()
を呼び出し、WakeUp
メッセージを取得するときにunstashAll()
を呼び出します。または、まったく別のことをすることもできます。アクターは非常に柔軟です。
アクターは実際にスリープすることはなく、常に着信メッセージを処理します。上に示したように、それが何を意味するかを定義できますが、基本的な原則は、メールボックス内のメッセージを処理しないようにアクターを一時停止することはできないということです。
スケジューラーに渡されたクロージャーの「送信者」を閉じています。これは、リングメッセージが間違ったアクターに送信されている可能性が高いことを意味します。代わりにこれを行う必要があります。
case Sleep(duration) =>
val s = sender
context.system.scheduler.scheduleOnce(duration) {
s ! Ring
}
}
Roland Kuhnの答えは主題をカバーしていますが、スケジューラーを使用する別の一般的なユースケースがあることを付け加えたいと思います。別のアクターにメッセージを送信し、このアクターが応答するのを待つとき、タイムアウトで待機を制限することは非常に一般的です。
otherActor ! Request(...)
context.system.scheduler.scheduleOnce(duration, self, WakeUp)
...
case Response(...) => ...
case WakeUp => context stop self