まず第一に、命令的でブロックする考え方を放棄しなければなりません。Akka は、すべてが非同期のときに最高の味を出します。他のアクターの返信を待ってブロックしないでください。代わりに、Future[T]
オブジェクトを取得してそれに関数を適用できます。この関数は、 future が完了したときに呼び出されます。
例を作ってみましょう: をSquareActor
取り、そのInt
2 乗を返す a があります。返信を求める正しい方法は次のとおりです。
squareActor ? 9 map {result =>
println(result) //81
}
//more code
非常に重要: を含むコード ブロックはブロックされprintln
ません。さらに多くのコードがすぐに実行され、しばらくしてコールバック メソッドが呼び出されます。
そうは言っても、ユースケースの実装を開始できます。私の理解が正しければ、アクターのリストと整数のリストがあります。すべての整数を正確に 1 つのアクターに送信したいとします。擬似コードは次のとおりです。
val actors: List[ActorRef] = //...
val numbers: List[Int] = //...
val actorsWithArguments: List[(ActorRef, Int)] = actors zip numbers
val futuresOfAny: List[Future[Any]] = actorsWithArguments map { case (actor, number) => actor ? number}
val futures: List[Future[Int]] = futuresOfAny map {_.mapTo[Int]}
val futureOfAllResults: Future[List[Int]] = Future.sequence(futures)
val future: Future[Int] = futureOfAllResults map { _.sum}
コードを理解するのに役立つように、意図的に明示的な型を残しました。一歩一歩進みましょう:
actorsWithArguments
List
タプルの です。各アイテムには、アクターとメッセージのペアが保持されます - (actor1, message1)
, (actor2, message2)
, ...
futuresOfAny
呼び出しのFuture
結果のリストが含まれています。次の理由で aを返します: a) 結果が (まだ) わかっていない、b) Akka が結果の型を知らない (応答メッセージ)actor ? number
?
Future[Any]
futures
各返信がInt
. 私たちはmapTo
それぞれFuture[Any]
にFuture[Int]
futureOfAllResults
List[Future[Int]]
aから への本当に素晴らしい変換を採用していFuture[List[Int]]
ます。言い換えれば、将来の結果のリストを、すべての項目を含む単一の将来の結果に変えただけです。
future
あなたの結果を保持します(将来も保持します)。
大量のコードだと思われる場合は、教育目的のためだけに作成されたものです。連鎖と型推論は魔法のようにできます:
val future = Future.sequence(actors zip numbers map { case (actor, number) => actor ? number} map { _.mapTo[Int]}) map { _.sum} }
最後に、あなたはあなたの結果を得ました。まあ、あなたは将来得るでしょう。その結果を別のアクターに送り返したい場合は、次のように言います。
future map {sum => otherActor ! sum}
//or even...
future map otherActor.!
これをすべて明確にするために、公式ドキュメントの先物に関する章を読むことを強くお勧めします。