5

假设我有一个非常简单的演员类,它接收任何消息并打印到控制台。

  class SimpleActor extends Actor{

    def receive: Receive = {
      case message =>
        println(s"[${this}][${self}] received message: ${message}")
    }
  }

  val simpleActor = actorSystem.actorOf(Props[SimpleActor], "simpleActor")
  simpleActor ! "Hey"

正如你所看到的,我同时使用thisselfhere,两者都有不同的值。它的输出类似于:

[pkg.ActorRunner$SimpleActor@65cca69][Actor[akka://ActorDemo/user/simpleActor#934141660]] received message: Hey

我想了解和之间的区别selfthis因为在复杂场景(生产系统)中,如果演员中断,例如:抛出一个异常,而不是我认为的值this会改变。

4

1 回答 1

8

this是对扩展Actor特征的对象的经典 java 引用,而对发送消息(或和或)所需的对象self的引用ActorRef!tell?ask

  • 您无法向this
  • 您不应该将引用传递给this外部演员,而将引用传递给self完全没问题,事实上,当您从另一个演员向演员发送消息时,它会隐式发送。如果你传递this给另一个对象,你将冒着actor状态封装的风险。请记住,与演员交流的唯一方式是通过消息,即ActorRef
  • self演员重启后将保持有效,也就是你可以继续向同一个ActorRef(自我)发送消息。只有当参与者停止时,对的引用才ActorRef不再有效,并且发送到该地址的消息将以死信结尾。
  • this演员重启后将不再有效。实例化一个新的类型对象Actor以清除可能因失败而受损的参与者状态。

重启是什么意思

除非故障是具体可识别的,否则不能排除第三个原因,从而得出需要清除内部状态的结论。如果主管决定它的其他孩子或自己不受损坏的影响——例如,因为有意识地应用错误内核模式——因此最好重新启动孩子。这是通过创建底层 Actor 类的新实例并将失败的实例替换为子 ActorRef 内的新实例来实现的;这样做的能力是将参与者封装在特殊参考中的原因之一。然后新的actor继续处理它的邮箱,这意味着重启在actor之外是不可见的本身有一个明显的例外,即发生故障的消息不会被重新处理。

演员参考和路径平等

请注意,由失败引起的actor重启仍然意味着它是同一个actor化身,即重启对于ActorRef的消费者是不可见的。

Actor引用和路径有什么区别?

参与者引用指定单个参与者,并且引用的生命周期与该参与者的生命周期相匹配;演员路径代表一个名称,该名称可能由演员居住,也可能不居住,并且路径本身没有生命周期,它永远不会变得无效。你可以创建一个actor路径而不创建一个actor,但是你不能创建一个actor引用而不创建相应的actor。
你可以创建一个actor,终止它,然后用相同的actor路径创建一个新的actor。新创建的演员是演员的新化身。这不是同一个演员。对旧化身的演员引用对新化身无效。即使它们具有相同的路径,发送到旧 Actor 引用的消息也不会传递到新化身。

于 2019-03-15T01:51:44.447 回答