【问题标题】:Actor and Future: Referring to an actor message within onCompleteActor 和 Future:在 onComplete 中引用 Actor 消息
【发布时间】:2015-10-13 05:16:51
【问题描述】:

在重构其他一些程序员编写的actor代码时,我遇到了在actorA中使用Future.onComplete回调,这违背了使用akka.pattern.pipe的最佳实践。这是一个坏主意,因为它暴露了竞争条件的可能性,因为 Future 实例可能在不同的线程上执行。

查看代码,我们看到在 onComplete 块中既没有 sender 也没有任何可变的 vars 被引用,所以它看起来很安全,至少对于 这个特定的场合。然而,让我感到疑惑的一个灰色区域是对url 的引用,尤其是text

是否有可能类似于Closing Over An Akka Actor Sender In The Receive 问题,发生竞争条件,使得在调用onComplete 回调时,text 的值已经引用了不同的参与者消息,导致所有地狱挣脱?

class B extends akka.actor.Actor {
  def receive = {
    case urlAndText: (String, String) => // do something
  }
}

class A extends akka.actor.Actor {
  case class Insert(url: String)

  def fileUpload(content: String): String = ??? // returns the url of the uploaded content
  val b = context.actorOf(Props(classOf[B]))
  def receive = {
    case text: String =>
      Future {
        fileUpload(text)
      } onComplete {
        case Success(url) =>
          b ! Insert(url, text) // will this be
      }
  }
}

【问题讨论】:

    标签: scala akka future


    【解决方案1】:

    text 的引用应该没问题。不同之处在于text 的每个“实例”都是绑定到当前匹配块范围的新变量(从case text ... 开始)。因此,创建的Future 接近于text 的值就好了。

    这与sender(或去糖时的sender())不同,后者实际上是在Actor trait 上定义的方法,它返回actor 收到的最新消息的发送者的ActorRef它被调用,因此可以在稍后调用时给出不同的值(当最终调用 FutureonComplete 时)。

    您也可以怀疑onComplete 的使用。更好的选择是:

    case text: String =>
      Future {
        fileUpload(text)
      } map { url => 
        Insert(url, text) 
      } pipeTo b
    

    现在失败也会被发送到b,而不是被悄悄吞下。

    【讨论】:

      【解决方案2】:

      在这种情况下,您不会遇到任何竞争条件,但正如您所指出的,通常以这种方式构造代码并不是一个特别好的主意。

      urltext 的引用都很好。 url 的值只是对成功完成的 Future 的提取,无论您是否在 Actor 中都不会改变。 text 的值是一个不可变字符串,在 Future 中关闭该值不会导致问题,因为该字符串实例是不可变的。

      正如您所说,关闭 sender 或 var 是一个问题,这是因为作为可变对象,这些值可能会在 Future 完成时发生变化,而不像不可变值那样,即使您关闭它们也会保持不变。

      【讨论】:

        猜你喜欢
        • 2021-09-11
        • 1970-01-01
        • 1970-01-01
        • 2012-09-02
        • 2019-08-20
        • 1970-01-01
        • 2015-05-29
        • 2015-01-06
        • 1970-01-01
        相关资源
        最近更新 更多