【问题标题】:Sender becomes Actor[akka://Main/deadLetters]Sender 成为 Actor[akka://Main/deadLetters]
【发布时间】:2013-12-18 05:02:56
【问题描述】:

我不知道为什么会出现错误“deadLetters

class MyActor extends Actor {

  private def getIdList = Future { blocking(getIdListSync) }

  private def getIdListSync = {
    val inputStreamRaw = new URL(url).openConnection.getInputStream
    val inputStream = scala.io.Source fromInputStream inputStreamRaw
    val json = parse(inputStream getLines() mkString "\n")
    val jsonIds = json \ "ids" \\ classOf[JInt]
    jsonIds take idLimit map (_.toInt)
  }

  def receive = {
    case Get =>

        //doesn't work, the error is "sender" becomes "Actor[akka://Main/deadLetters]"

//      getIdList onComplete {
//        case Success(idList) =>
//          sender ! Result(idList)
//
//        case Failure(e) => // todo
//      }

      //works well
      val idList = getInternalIdListSync
      sender ! Result(idList)

  }
}

如你所见,sender 在标题为getIdList 的方法中使用Futureblocking 的情况下变为Actor[akka://Main/deadLetters]。这是为什么?我不应该使用它吗?

【问题讨论】:

    标签: multithreading scala akka


    【解决方案1】:

    问题是您在异步功能块中调用sender。有一个简单的规则:

    永远不要关闭可能异步执行的代码块中的 sender 方法

    sender 是一个函数,它返回当前处理的消息的发送者。问题是,如果你在像onComplete 这样的回调中调用sender,这个回调会异步执行。这意味着在此期间参与者可能会处理其他消息,因此sender 函数可能不会报告原始消息的发送者。

    避免这种情况的一种方法是在执行异步代码之前将发送者存储在局部变量中:

    def receive = {
      case Get =>
        val s = sender
    
        // call an asynchronous function
        myAsyncFunction onComplete{ result =>
          s ! result
        }
    }
    

    另一种方法是使用 @Vadzim 指出的 akka pipeTo 函数:

    import akka.pattern.pipe
    
    def receive = {
      case Get =>
        // call an asynchronous function
        val result = myAsyncFunction
    
        result pipeTo sender
    }
    

    更多信息可以在akka文档中找到:http://doc.akka.io/docs/akka/snapshot/scala/futures.html#Use_With_Actors

    【讨论】:

    • 对 Future (getIdList) 使用异步方法是否明智,还是应该只使用同步方法 (getIdListSync)?
    • 这取决于演员的任务是什么。如果这是参与者应该执行的唯一任务,那么使用同步变体就可以了。在这种情况下,应该使用多个相同类型的参与者和一个调度程序进行缩放。另一方面,如果演员在创建列表时应该做其他事情,你应该考虑使用异步变体。
    • Aaaa,因此只有在第一个任务正在执行时还有另一个任务(或总体上不止一个任务)要处理时,才使用多线程(和 Futures),对吗?
    • 对。在actor中接收消息并异步执行所有工作以立即接收下一条消息没有多大意义(面团,有用例,例如在远程机器上执行任务)。为同一任务生成多个 Actor 可为您提供更多控制权(例如,您可以定义并行工作的 Actor 数量)
    【解决方案2】:

    随便用

    import akka.pattern.pipe
    getIdList pipeTo sender
    

    解释见: Akka: Send a future message to an Actor

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多