15

私は Akka にかなり慣れていないので、リファレンス マニュアルで答えを見つけることができませんでした。

3 台のマシン (A、B、C) のクラスターにリモート アクターが分散しているとします。この場合、各マシンには 1 つのアクターが存在し、他の 2 つのアクターには他の 2 つのアクターへのactorRef があります。

Machine A:
A (real actor)
-> B (ref)
-> C (ref)

Machine B:
-> A (ref)
B (real actor)
-> C (ref)

Machine C:
-> A (ref)
-> B (ref)
C (real actor)

アクター A は次のコードを実行します。

bRef ! msg1
bRef ! msg2

アクター B は、メッセージ ハンドラーで次のコードを実行します。

case msg1 => 
    cRef ! msg3
    aRef ! msg4

アクター C は、メッセージ ハンドラーで次のコードを実行します。

case msg3 => 
    aRef ! msg5

次の仮定を立てることができますか (もしあれば):

  1. アクター B は、msg2 を取得する前に msg1 を取得します

  2. アクター A は msg4 を取得する前に msg5 を取得します

そして、おそらく上記の理解につながるフォローアップの質問: Is message sent by the ! オペレーターはネットワークを介して真に非同期に処理するのか、それとも受信メールボックスがそれを取得するまで待機するのか? つまり、行を行います

bRef ! msg1

アクター B がメールボックスにメッセージを取得するまでブロックするか、配信を処理して実行を続けるスレッドを生成するか

bRef ! msg2

アクター B が msg1 を受け取ったことを知る前に?

4

2 に答える 2

9

(1)の場合、msg1がmsg2の前にディスパッチャによってエンキューされることが保証されます。それらがエンキューされた後に実際に何が起こるかは、実際には使用するディスパッチャによって異なります:http: //akka.io/docs/akka/1.1.2/scala/dispatchers.html、しかしあなたの場合、Bが両方を受け入れることができる限りメッセージの場合、msg2の前に常にmsg1を受信します。

(2)の場合、この保証はありません。!!メソッドは、メッセージがターゲットアクターのメールボックスによって受け入れられたときではなく、ディスパッチャがメッセージをキューに入れるとすぐに戻ります。その後、送信は別のスレッドで行われ、あらゆる種類の競合状態の影響を受けます。

メッセージは!によって送信されます ネットワークを介したオペレーターは本当に非同期ですか、それとも受信メールボックスがそれを取得するまで待機しますか?

ローカルアクターでBoundedMailboxを使用して、ディスパッチャーへのメッセージのキューイングが!:と非同期であることを示すことができます。

class TestActor extends Actor {
  val mailboxCapacity = BoundedMailbox(capacity = 1)
  self.dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("test", 1, mailboxCapacity).build

  def receive = {
    case x: String => 
      Thread.sleep(1000)
      println("Received message")
    case _ => 
  }
}

val t = Actor.actorOf[TestActor]
t.start()

t ! "one"; t ! "two"; t ! "three"; println("Main thread");

プリント:

scala>     t ! "one"; t ! "two"; t ! "three"; println("Main thread");
Received message
Main thread

scala> Received message
Received message

つまり、メッセージが配信されるかどうかさえわからないうちに、メインスレッドでのコード実行が続行されます。この場合、ディスパッチャにpushTimeoutを設定し、Thread.sleepをタイムアウトより長く待機させると、メッセージ送信が簡単にタイムアウトになる可能性があります。

これを使用することと比較してください!!:

scala>     t !! "one"; t !! "two"; t !! "three"; println("test");
Received message
Received message
Received message
test

だから、これを念頭に置いて。(2)を達成する方法は次のとおりです。

case msg1 =>
  cRef !! msg3
  aRef ! msg4 
于 2011-06-01T14:36:48.143 に答える
1

Erlang は最初の保証を提供しますが、2 番目の保証は提供しません。Akka は最初の保証も提供するかもしれませんが、2 番目の保証は提供しません。

フォローアップの質問に対する答えがわかりません。

于 2011-06-01T14:19:43.300 に答える