加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala – Akka演员,期货和封闭

发布时间:2020-12-16 09:10:10 所属栏目:安全 来源:网络整理
导读:我在 Akka docs中看到,从封闭的演员关闭变量是很危险的. Warning In this case you need to carefully avoid closing over the containing actor’s reference,i.e. do not call methods on the enclosing actor from within the anonymous Actor class. Thi
我在 Akka docs中看到,从封闭的演员关闭变量是很危险的.

Warning

In this case you need to carefully avoid closing over the
containing actor’s reference,i.e. do not call methods on the
enclosing actor from within the anonymous Actor class. This would
break the actor encapsulation and may introduce synchronization bugs
and race conditions because the other actor’s code will be scheduled
concurrently to the enclosing actor.

现在,我有两个演员,其中一个要求从第二个演员,并做一些结果.在下面的这个例子中,我已经放在一起,演员累加器从演员NumberGenerator检索数字,并将它们相加,并在路上报告总和.

这可以用至少两种不同的方式完成,因为这个例子显示了两个不同的接收函数(A和B).两者之间的区别在于A不会关闭柜台变量;而是等待一个整数并将其加起来,而B创建一个关闭计数器的未来,并且总和.这发生在一个匿名的演员,只是为了处理onSuccess,如果我明白了解如何工作.

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
  }
}

在这种情况下使用闭包是绝对邪恶的吗?当然,我可以使用一个AtomicInteger而不是一个Int,或者在一些使用netty的网络场景下,在threadsafe通道上发出一个写操作,但这不是我的观点.

有可能问可笑的是:未来的onSuccess是否可以在这个演员身上执行,而不是匿名的中间演员,而不是在接收功能中定义一个案例?

编辑

更清楚的是,我的问题是:有没有办法强制一系列期货与给定的演员一样运行?

解决方法

问题是onSuccess将运行在与演员接收的线程不同的线程中.您可以使用pipeTo方法,或使用 Agent.使反对AtomicInteger可以解决问题,但不是那么干净 – 就是打破了Actor模型.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读