web-dev-qa-db-ja.com

アクター内でAkkaスケジューラーを使用することは可能ですか?

俳優をしばらく寝かせる可能性が欲しいです。俳優は、どれくらいの時間寝るかを自分で決める必要があります。 Thread.sleep()はこれを行うための推奨される方法ではないため、akkaでスケジューラーを使用することを考えました。したがって、私は、別の俳優が起こされるために登録できる俳優を定義しました。

class Scheduler extends Actor {

  def receive = {
    case Sleep(duration) => context.system.scheduler.scheduleOnce(duration) {
      sender ! Ring
    }
  }
}

ただし、送信側のアクターはリングメッセージを受信しません。だから私の質問は

  • アクター内でスケジューラーを使用したスケジューリングが推奨されていますか?
  • 送信側のアクターがリングメッセージを受信しないのはなぜですか?
  • これが不可能な場合、問題を解決するための推奨される方法は何ですか?
28
Felix Reckers

最初にタイトルの質問に答えましょう。はい、アクター内でスケジューラーを使用することは可能です。

_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()を呼び出します。または、まったく別のことをすることもできます。アクターは非常に柔軟です。

俳優がしないこと

アクターは実際にスリープすることはなく、常に着信メッセージを処理します。上に示したように、それが何を意味するかを定義できますが、基本的な原則は、メールボックス内のメッセージを処理しないようにアクターを一時停止することはできないということです。

44
Roland Kuhn

スケジューラーに渡されたクロージャーの「送信者」を閉じています。これは、リングメッセージが間違ったアクターに送信されている可能性が高いことを意味します。代わりにこれを行う必要があります。

case Sleep(duration) => 
  val s = sender
  context.system.scheduler.scheduleOnce(duration) {
    s ! Ring
  }
}
16
Ryan LeCompte

Roland Kuhnの答えは主題をカバーしていますが、スケジューラーを使用する別の一般的なユースケースがあることを付け加えたいと思います。別のアクターにメッセージを送信し、このアクターが応答するのを待つとき、タイムアウトで待機を制限することは非常に一般的です。

otherActor ! Request(...)
context.system.scheduler.scheduleOnce(duration, self, WakeUp)
...
case Response(...) => ...
case WakeUp => context stop self
0
Eyal Farago