演员和未来:引用onComplete中的演员消息

时间:2015-10-13 05:16:51

标签: scala akka future

在重构其他程序员编写的actor代码时,我在actor infoFiltered:("_TOTAL_" == 0) ? " " : " (_MAX_ row)"中遇到了Future.onComplete回调的使用,这违反了使用A的最佳做法。这是一个坏主意,因为它暴露了竞争条件的可能性,因为akka.pattern.pipe实例可能在不同的线程上执行。

查看代码,我们发现在Future块中没有引用sender或任何可变的var,因此它看起来非常安全,至少对于这个特定场合。但是,让我感到疑惑的一个灰色区域是对onComplete的引用,特别是url

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

text

2 个答案:

答案 0 :(得分:5)

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

这与sender()(或去糖时为Actor)不同,后者实际上是在ActorRef特征上定义的方法,该特征返回发件人的Future调用它的actor接收的最新消息,因此在稍后调用时(最终调用onComplete的{​​{1}}时)可以给出不同的值。

你也对使用onComplete怀疑是对的。更好的选择是:

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

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

答案 1 :(得分:1)

在这种情况下,你不会遇到任何竞争条件,尽管如你所知,通常以这种方式构建代码并不是一个特别好的主意。

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

正如您所说,关闭sender或者var是一个问题因为是可变对象,这些值可能会在Future完成时改变,而不可变值即使关闭也会保持不变在他们身上。