2013-05-24 8 views
10

自分のスレッドからアクカのアクタと交流したいです。現在、私はそうです:アクタの外のアクタとの交流

val res = Await.result(aref ? GroupReceive(fromRank), timeout.duration).asInstanceOf[T] 

しかし、これは実際に私のスレッドとどのように対話するのですか?受信を非同期にすることを希望します。つまり、受信中にスレッドをハングアップして他の作業を許可したいとします。私は最近、Akka inboxシステムについて読んでいます。 inbox akka api

は私が待っていますが、新しい俳優たびに作成することを思い出すと思います。 await + askとinboxの違いは何ですか?また、受信トレイを作成し、それを使って "外部"の俳優とコミュニケーションする方法の例を教えてもらえますか?ただ、明確にする

EDIT 、私はその後、目を覚ます、それはCPUコアを占有停止し、それが何かを受信するまで動作するように他のスレッドを残しておきたい、働き続けるために同じスレッドを望んでいません再び。結果を待つまで待つブロック、現在のスレッドを使用して、アッカの未来のマニュアルに書かれたよう

+2

akkaでは、 'asInstanceOf'の代わりに' mapTo [Type] 'をよく使うべきです。 – 4lex1v

+0

どのような利点がありますか? :) – Felix

+1

'asInstanceOf'は、失敗したときに例外をスローします。 'mapTo'は失敗した未来を返します。 – drexin

答えて

8

import scala.concurrent.Await 
import akka.pattern.ask 
import akka.util.Timeout 
import scala.concurrent.duration._ 

implicit val timeout = Timeout(5 seconds) 
val future = actor ? msg // enabled by the “ask” import 
val result = Await.result(future, timeout.duration).asInstanceOf[String] 

これは、現在のスレッドをブロックし、それが返事だと「完全」未来への出演を待つことになります。

Use With Actors

+0

これと受信トレイの使用? – Felix

+0

@Felix akkaさんのDSLを一度も使用していませんが、私は受信箱の主な使い方は1)複数の返信を受け取り、2)他の俳優のライフサイクルを見ることができないことです。 [Inbox](http://doc.akka.io/docs/akka/2.2-M3/scala/actors.html) – 4lex1v

+0

@seniaはまだあなたに同意していませんが、ActorSelectionを介してActorRefでFutureを返すように依頼しますが、新しいActorを作成します – 4lex1v

0

あなたは、代わりにするonSuccess、ONFAILUREとonCompleteのような非ブロックコールバックを使用し、待つを使用しない、呼び出し側でブロックしたくない場合。これを行うと、ExecutionContextがask(?)の時点でスコープ内にあるものに、将来のタスクが入れられます。応答が受け取られると、このコールバックはExecutionContextを介して非同期に呼び出されます。こうすることで、アクターへの要求を行っているスレッドですべてを一緒にブロックすることを回避し、ExecutionContextに関連付けられたスレッドプールでコールバックを処理します。

はまた、私はあなたが言及受信トレイのものをREPLで俳優のものをテスト目指していると考えている(少なくとも、それは何ActorDsl上のドキュメント)の状態。あなたは俳優の外から尋ねることを使用しているアプローチに固執してください。 akkaは、非俳優の俳優の呼び出しのためのフードの下でのコミュニケーションに必要な短命の俳優を作成させます。上記のように非ブロッキングコールバックに切り替えてください。私はそれがあなたが探しているものだと信じています。

4

Await.receiveは、Scalaの並行処理APIの一部であり、役者とは何の関係もありません。その目的は、提供された未来が完了するまで、またはタイムアウト制限が発生し、タイムアウト例外ですべてが終了するまで、現在のスレッドをブロックすることです。

オペレータ?が実際の俳優からの応答を待っているの唯一の目的で、一時的な俳優を作成します頼むはaref変数によって指さ、あなたが受信した応答でお願いオペレータを呼び出したときにあなたが得た未来を完了します。

あなたのコードは基本的にスレッド全体をブロックしています。指示されているように、現在のスレッドを解放し、他の作業を続行したい場合は、コールバックを将来に追加することができます。

implicit val ctx: ExecutionContext = //provide execution context here 
implicit val timeout: Timeout = // provide timeout here 
aref ? GroupReceive(fromRank)) onSuccess { res => 
    //do something with res here, asynchronously 
} 
// some other code which runs without being blocked... 

上記のコードでは、前述した俳優のDSLを書き換えることができます。後者のバージョンはまた後に、GroupReceiveメッセージを送信し、応答を待ち、新しい一時的な俳優を作成

import akka.actor.ActorDSL._ 
implicit val actorSystem: ActorSystem = // provide an actor system here or any actor ref factory 

actor(new Act { 
    aref ! GroupReceive(fromRank) 
    context.setReceiveTimeout(timeout) //optional 
    become { 
    case ReceiveTimeout => { 
     //handle the timeout 
     context.stop(self) 
    } 
    case res => { 
     //do your thing with res, asynchronously 
     context.stop(self) 
    } 
    } 
} 

//some other code which won't wait for the above operations 

それはそれ自身を殺す。

結論は、俳優からメッセージを受け取るためには、俳優でなければなりません。俳優はただActorRef以外にメッセージを送ることはできません。

したがって、舞台裏で一時的な俳優を作成し、この一時的な俳優のライフサイクル自体を管理する尋問パターンを使用するか、作業する素敵な簡単な未来を暴露するか、または一時的な俳優を自分で作成することができますあなたはそのライフサイクルを管理しなければなりません(つまり、仕事を終えたらそれを忘れないようにしてください)

あなたに最適なオプションを選択してください。

+0

あなたの応答のDSLのサンプル部分:これは、より速い要求/応答のために、より待ち時間の長い要求に対しては機能しますが、時間がかかるために失敗するかもしれません。DSLの動作は、 ://stackoverflow.com/questions/17851849/the-actor-dsl-example-from-akka-doc – radekg

関連する問題