比方说,我有一个非常简单的actor类,该类接收任何消息并打印到控制台。
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"
如您所见,我在这里同时使用this
和self
,并且两者都有不同的值。其输出类似于:
[pkg.ActorRunner$SimpleActor@65cca69][Actor[akka://ActorDemo/user/simpleActor#934141660]] received message: Hey
我想了解self
和this
之间的区别,因为在复杂的场景(生产系统)中,如果演员中断,例如:抛出比我认为的this
值高的异常被改变。
答案 0 :(得分:7)
this
是对扩展了Actor
特性的对象的经典Java引用,而self
是对ActorRef
的引用,这是您需要发送消息的对象({{1 }}或!
和tell
或?
)
ask
this
的引用时,最好不要在actor外部传递对this
的引用,实际上,当您从另一个actor向一个actor发送消息时,它是隐式发送的。如果将self
传递给另一个对象,则可能会冒充actor的状态封装。请记住,与演员交流的唯一方法是通过消息,即与演员this
ActorRef
将保持有效,也可以将消息继续发送到同一self
(自身)。仅当参与者停止活动时,对ActorRef
的引用将不再有效,并且发送到该地址的消息将以死信结尾。ActorRef
将不再有效。实例化类型为this
的新对象,以清除由于故障而可能受损的参与者状态。 除非可以明确识别故障,否则不能排除第三个原因,从而得出结论,需要清除内部状态。如果主管决定其其他孩子或本身不受腐败影响,例如由于有意识地应用了错误内核模式-因此最好重新启动子级。 这是通过创建基础Actor类的新实例并将失败的实例替换为孩子的ActorRef中的新实例来完成的;这样做的能力是将参与者封装在特殊引用中的原因之一。然后,新的actor将继续处理其邮箱,这意味着在actor自身外部看不到重新启动,但值得注意的例外是发生故障的消息未得到重新处理。
Actor Reference and Path Equality
请注意,由于故障导致的Actor重新启动仍然意味着它是同一Actor的化身,即ActorRef的使用者看不到重新启动。
What is the Difference Between Actor Reference and Path?
演员参考指定单个演员,参考的生命周期与该演员的生命周期相匹配;一个actor路径代表一个名称,该名称可能由actor占用也可能没有,并且该路径本身没有生命周期,因此永远不会无效。您可以在不创建角色的情况下创建角色路径,但是在不创建相应角色的情况下不能创建角色引用。
您可以创建一个actor,将其终止,然后使用相同的actor路径创建一个新actor。新创建的演员是演员的新化身。不是同一位演员。 演员对旧的化身的引用对新的化身无效。发送到旧演员参考的消息即使路径相同,也不会传递到新角色。