使用Akka 2.0尝试向自己发送消息(使用ask模式)
import akka.pattern.ask
import scala.concurrent.{Await, Future}
import akka.actor.{Props, Actor, ActorSystem}
import scala.concurrent.duration._
import akka.util.Timeout
object askTest extends App{
implicit val timeout = Timeout(5 seconds)
val system = ActorSystem("AskTestSystem")
val myActor = system.actorOf(Props(new TestActor), name = "myActor")
val future: Future[Foo] = ask(myActor, Foo("test")).mapTo[Foo]
val result = Await.result(future, timeout.duration)
println(result)
}
case class Foo(name:String){
override def toString = "Foo "+name
}
class TestActor extends Actor {
def receive = {
case Foo(a) => self ! Foo("buzz "+a)
case any => println(any+" that was unexpected")
}
}
Run Code Online (Sandbox Code Playgroud)
但它与Timeout异常崩溃并带有以下跟踪:
Exception in thread "main" java.util.concurrent.TimeoutException: Futures timed out after [5 seconds]
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:96)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:100)
at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:107)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
at scala.concurrent.Await$.result(package.scala:107)
at akkaTest.askTest$delayedInit$body.apply(askTest.scala:33)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
at scala.App$class.main(App.scala:71)
at akkaTest.askTest$.main(askTest.scala:13)
at akkaTest.askTest.main(askTest.scala)
Run Code Online (Sandbox Code Playgroud)
您的代码执行您告诉它要执行的操作:actor无限期地向自己发送消息.因为它将消息发送给除self以外的任何人,所以您的ask模式无法正常工作,因为ask正在等待将消息发送给发件人,而不是自己.
self是对当前actor的引用,当您希望actor向自己发送消息时使用它.sender是对已发送当前正在处理的消息的actor的引用.如果您想"回复"发件人,请使用它.
askpattern创建一个隐式actor,它sender在目标actor中成为引用 - 这是非常自然的.因此,您需要更改self ! Foo("buzz " + a)为sender ! Foo("buzz " + a),并且您的代码将起作用.
您可以将邮件发送到self,但不能等待回复。因为直到完成对当前消息的处理,您才收到新消息;如果使用ask,您将在得到对新消息的答复之前完成对当前消息的处理!因此,您正在创建一个僵局。
但是,对于所涉及的代码,您根本不要求self答复。由创建的actor ask正在等待来自的答复myActor,但没有得到答复(因为的代码TestActor未发送任何答复,self而是发送了一条消息给)。
您可以self ! message通过稍作更改来查看效果TestActor:
case class Bar(name: String)
class TestActor extends Actor {
def receive = {
case Foo(a) => self ! Bar(a)
case Bar(a) => println("Got a message to self: " + a)
case any => println(any+" that was unexpected")
}
}
Run Code Online (Sandbox Code Playgroud)