gsi*_*ard 12 closures scala future actor akka
我在Akka文档中读到,关闭来自封闭演员的变量是危险的.
警告
在这种情况下,您需要小心避免关闭包含actor的引用,即不要在匿名Actor类中调用封闭actor上的方法.这会打破actor封装,并可能引入同步错误和竞争条件,因为其他actor的代码将同时调度到封闭的actor.
现在,我有两个演员,其中一个从第二个请求某些东西并对结果做了一些事情.在下面的这个示例中,我放在一起,演员Accumulator从演员NumberGenerator中检索数字并将它们相加,并沿途报告总和.
这可以通过至少两种不同的方式完成,因为该示例显示具有两个不同的接收功能(A对B).两者之间的区别在于A不会关闭计数器变量; 相反,它等待一个整数并将其求和,而B创建一个关闭计数器并完成总和的Future.如果我正确理解这是如何工作的,那么这是在为处理onSuccess而创建的匿名actor中发生的.
import com.esotericsoftware.minlog.Log
import akka.actor.{Actor, Props}
import akka.pattern.{ask, pipe}
import akka.util.Timeout
import akka.util.duration._
case object Start
case object Request
object ActorTest {
var wake = 0
val accRef = Main.actorSystem.actorOf(Props[Accumulator], name = "accumulator")
val genRef = Main.actorSystem.actorOf(Props[NumberGenerator], name = "generator")
Log.info("ActorTest", "Starting !")
accRef ! Start
}
class Accumulator extends Actor {
var counter = 0
implicit val timeout = Timeout(5 seconds)
// A: WITHOUT CLOSURE
def receive = {
case Start => ask(ActorTest.genRef, Request).mapTo[Int] pipeTo self
case x: Int => counter += x; Log.info("Accumulator", "counter = " + counter); self ! Start
}
// B: WITH CLOSURE
def receive = {
case Start => ask(ActorTest.genRef, Request).mapTo[Int] onSuccess {
case x: Int => counter += x; Log.info("Accumulator", "counter = " + counter); self ! Start
}
}
}
class NumberGenerator extends Actor {
val rand = new java.util.Random()
def receive = {
case Request => sender ! rand.nextInt(11)-5
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下使用闭包绝对是邪恶的吗?当然我可以使用AtomicInteger而不是Int,或者在某些网络场景中使用netty,在线程安全通道上发出写操作,但这不是我的观点.
要冒这个荒谬的风险:有没有办法让Future的onSuccess在这个 actor中执行而不是匿名的中间actor,而不在receive函数中定义一个case ?
编辑
更清楚地说,我的问题是:有没有办法迫使一系列Futures在与给定Actor相同的线程中运行?
实现此类设计的最简单方法是使用"即发即忘"语义:
class Accumulator extends Actor {
private[this] var counter = 0
def receive = {
case Start => ActorTest.genRef ! Request
case x: Int => {
counter += x
Log.info("Accumulator", "counter = " + counter)
self ! Start
}
}
}
Run Code Online (Sandbox Code Playgroud)
此解决方案完全异步,您不需要任何超时.
| 归档时间: |
|
| 查看次数: |
3339 次 |
| 最近记录: |