下面的代码使用2个问题,最初似乎应该打印&#34;这应该在actor1中打印,但大部分时间都不会因为接收方法完成的竞争条件而导致&#34; < / strong>即可。 然而,在“接收”之间似乎存在竞争条件。方法完成和未来的整理,因此没有打印。 这是akka的预期行为吗?这是一个错误吗? 我试图避免使用&#39;问&#39;尽可能使用&#39;告诉&#39;相反,但有时候它是必须的。
import akka.actor._
import akka.routing.SmallestMailboxPool
import akka.util.Timeout
import akka.pattern.ask
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
object ActorsAskingStuff extends App {
val system = ActorSystem("abc-system")
val actor1 = system.actorOf(Props[Actor1].withRouter(SmallestMailboxPool(1)), "actor1")
actor1 ! 5
}
class Actor1 extends Actor {
implicit val timeout = Timeout(60 seconds)
val actor2: ActorRef = context.actorOf(Props[Actor2].withRouter(SmallestMailboxPool(1)), "actor2")
override def receive: Receive = {
case _ =>
println("actor1 was called")
actor2 ? "hello" onComplete {
case Success(a) => println(a)
case Failure(b) => println("FAILURE")
}
}
}
class Actor2 extends Actor {
implicit val timeout = Timeout(6 seconds)
val actor3: ActorRef = context.actorOf(Props[Actor3].withRouter(SmallestMailboxPool(1)), "actor3")
override def receive: Actor.Receive = {
case _ =>
println("actor2 was called")
actor3 ? "hello" map {
_ =>
println("Actor2 completed the future")
sender ! "This should be printed in actor1 but most of the time wont because of a race condition with the receive method finishing"
}
// uncomment this to make it work
//Thread.sleep(100)
}
}
class Actor3 extends Actor {
override def receive: Actor.Receive = {
case _ =>
println("actor3 was called")
sender ! "I'm actor3"
}
}
答案 0 :(得分:3)
执行此操作时,您将关闭sender
:
actor3 ? "hello" map {
_ =>
println("Actor2 completed the future")
sender ! "This should be printed in actor1 but most of the time wont because of a race condition with the receive method finishing"
}
此时sender
可能已发生变化。为了避免关闭sender
,您可以像这样重写:
val originator = sender()
actor3 ? "hello" map {
_ =>
println("Actor2 completed the future")
originator ! "This should be printed in actor1 but most of the time wont because of a race condition with the receive method finishing"
}
在此时进入基于Future
的回调(例如onComplete
或map
)后,演员认为已完成当前消息的转发并转到下一条消息在邮箱中(如果有)。发生这种情况时,sender()
只是一个def,它返回可能发生变化的var
的值,它将返回新的ActorRef
(更多消息)或没有(deadletter)如果没有消息。
您可以查看此帖子了解更多信息: sender inside a future