Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 阿克卡演员-发送者指向死信_Scala_Asynchronous_Akka_Actor - Fatal编程技术网

Scala 阿克卡演员-发送者指向死信

Scala 阿克卡演员-发送者指向死信,scala,asynchronous,akka,actor,Scala,Asynchronous,Akka,Actor,考虑以下示例: case class Payload(message: String, async: Boolean) class EchoActor extends Actor { override def receive: Receive = { case Payload(message, async) => if (async) Future { println(s"from: $sender") sender ! messa

考虑以下示例:

case class Payload(message: String, async: Boolean)

class EchoActor extends Actor {
  override def receive: Receive = {
    case Payload(message, async) =>
      if (async) Future {
        println(s"from: $sender")
        sender ! message
      } else {
        println(s"from: $sender")
        sender ! message
      }
  }
}

def main(args: Array[String]): Unit = {
  val system = ActorSystem("demo")
  val echo = system.actorOf(Props[EchoActor])
  implicit val timeout = Timeout(2 seconds)

  (echo ? Payload("Hello", async = false)).mapTo[String].foreach(println(_))
  (echo ? Payload("Async Hello", async = true)).mapTo[String].foreach(println(_))

  StdIn.readLine()
  system.terminate()
}
控制台输出:

from: Actor[akka://demo/temp/$a]
Hello
from: Actor[akka://demo/deadLetters]
[INFO] [04/13/2017 19:56:58.516] [demo-akka.actor.default-dispatcher-4] [akka://demo/deadLetters] Message [java.lang.String] from Actor[akka://demo/user/$a#2112869650] to Actor[akka://demo/deadLetters] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
i、 e.当从另一个线程访问时,发送方指向死信

这背后的原因是什么? 是虫子吗

尽管如此,我们可以保留对实际发件人的引用以使其正常工作:

if (async) {
  val currentSender = sender()
  Future {
    println(s"from: $currentSender")
    currentSender ! message
  }
}

但是。。。难道没有更好的方法吗?

这不是一个bug,而是一个记录在案的行为-


使用
Future
意味着调用一个匿名函数,该函数不是
Actor
类的实例,因此您的
sender()
ref被映射到
deadLetters

邮箱
pipe
模式是更好的方法

import akka.pattern.pipe

class EchoActor extends Actor {
  override def receive: Receive = {
    case Payload(message, async) =>
      if (async) {
        Future {
          message
        }.pipeTo(sender) 
      } else {
        sender ! message
      }
  }
}
问题在于
sender
是一个函数,它的值只有在处理传入消息的同一线程上调用时才有效。当您在将来调用
sender
时,它是从另一个线程在另一个时间点调用的,特别是在actor的receive函数已经返回之后


pipeTo
在接收函数返回之前,在与参与者相同的线程上捕获当前发送者的值。这实际上与使用
currentSender
值的方法相同。

这实际上是一种正确的方法。顺便说一句。您的代码示例仍然在
println
中异步访问
sender
。更好的解决方案是将其放入
Future
块之前的
val
中,并参考
Future
块中的内容。