在重构其他程序员编写的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
答案 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)
在这种情况下,你不会遇到任何竞争条件,尽管如你所知,通常以这种方式构建代码并不是一个特别好的主意。
对url
和text
的引用都很好。 url
的值只是对已成功完成的Future的提取,并且无论您是否在Actor中都不会改变。 text
的值是一个不可变的字符串,在Future中关闭该值不应该导致问题,因为该字符串实例是不可变的。
正如您所说,关闭sender
或者var是一个问题因为是可变对象,这些值可能会在Future完成时改变,而不可变值即使关闭也会保持不变在他们身上。