与演员之外的Akka演员互动

时间:2013-05-24 09:02:55

标签: scala asynchronous akka actor inbox

我想从我自己的线程与Akka演员互动。目前,我喜欢这样:

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

但我不确定这实际上是如何与我的线程交互的?我希望接收是异步的,即我想在接收时挂断线程以允许完成其他一些工作。我刚刚读到了有关Akka收件箱系统的信息。 inbox akka api

我想我曾经记得Await每次创造一个新演员。 await + ask和inbox之间有什么区别,有人可以给我一个如何创建收件箱并使用它与“外部”演员交流的例子吗?

修改 只是为了澄清,我不希望相同的线程继续工作,我希望它停止占用cpu-core并让其他线程工作直到它收到一些东西,然后再次唤醒。 / p>

3 个答案:

答案 0 :(得分:8)

如Akka的Future文档中所述,使用Await会阻止当前线程,直到等待结果为止。

实施例

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]
  

这将导致当前线程阻止并等待Actor“完成” Future以及它的回复。

Use With Actors

答案 1 :(得分:4)

Await.receive是Scala并发API的一部分,与actor无关。它的目的是阻止当前线程,直到提供的未来完成,或者超时限制启动并且整个事件以超时异常结束。

ask运算符?确实会创建一个临时actor,其唯一目的是等待aref变量指向的actor的回复,并完成你在调用ask时得到的未来收到回复的运营商。

所以你的代码基本上阻止了整个线程。如上所示,如果你想释放当前的线程并继续做其他工作,你可以附加一个回调给未来。

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重写:

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

后一个版本还创建了一个新的临时actor,它发送GroupReceive消息,然后等待回复,然后它自杀。

最重要的是,为了接收来自演员的消息,您必须自己是演员。演员不能只将消息发送到ActorRef以外的其他内容。

所以要么你使用ask模式在幕后创建一个临时演员并管理这个临时演员的生命周期本身,向你展示一个很好的简单未来,或者你可以自己创建临时演员,但是你必须管理它的生命周期(即记得在它完成工作后杀死它)

选择最适合您的选项。

答案 2 :(得分:0)

如果您不想在主叫方上阻止,则不要使用Await,请使用非阻塞回调,例如onSuccess,onFailure和onComplete。当你这样做时,未来的任务被放入在ask(?)的范围内ExecutionContext的范围内。收到响应时,将通过ExecutionContext异步调用此回调。这样就可以避免在向actor发出请求的线程中阻塞所有进程,然后在与ExecutionContext绑定的线程池中处理回调。

此外,我相信你提到的收件箱内容是为了测试REPL中的演员内容(至少是ActorDsl上的文档)。坚持使用来自演员之外的问题的方法。让akka创建一个短暂的演员,它需要进行非演员和演员之间的沟通。然后按照我的建议切换到非阻塞回调。我相信这就是你要找的东西。

相关问题