与演员之外的Akka演员互动

Fel*_*lix 11 asynchronous scala inbox actor akka

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

val res = Await.result(aref ? GroupReceive(fromRank), timeout.duration).asInstanceOf[T]
Run Code Online (Sandbox Code Playgroud)

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

我想我曾经记得Await每次创造一个新演员.await + ask和inbox之间有什么区别,有人能举例说明如何创建收件箱并使用它与"外部"的演员进行交流吗?

编辑 只是为了澄清,我不希望同一个线程继续工作,我希望它停止占用cpu-core并让其他线程工作,直到收到一些东西,然后再次唤醒.

4le*_*x1v 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]
Run Code Online (Sandbox Code Playgroud)

这将导致当前线程阻塞并等待Actor用它的回复"完成" Future.

与演员一起使用


Mar*_*ila 5

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...
Run Code Online (Sandbox Code Playgroud)

上面的代码可以用您上面提到的actor 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
Run Code Online (Sandbox Code Playgroud)

后一个版本还创建了一个新的临时角色,该角色发送GroupReceive消息,然后等待答复,此后它会杀死自己。

底线是,要接收演员的消息,您必须自己是演员。演员不能只是向某人以外的人发送信息ActorRef

因此,您要么使用问号模式在幕后创建一个临时演员并管理该临时演员的生命周期,向您展示一个美好的简单未来,要么可以自己创建临时演员,但是您必须管理它的生命周期(即完成工作后记得杀死它)

选择最适合您的选项。