把消息从非演员(non-actor)发送给演员(actor)是一种不良实践吗?

10

假设我有一个类,其中有一个类型为Actor的属性actor_。 我这样做有问题吗?

def someMethod() = {
  actor_ ! "HELLO"
}

或者发送消息是否总是应该由另一个 Actor 完成?

def someMethod() = {
  Actor.actor { actor_ ! "HELLO" }
}
2个回答

8
这取决于情况。当您从非actor代码向actor发送消息时,会自动创建一个ActorProxy并存储在线程本地中。这会产生潜在的内存泄漏,尽管很小,因为ActorProxy在线程被GC之前不会被GC。 ActorProxy实际上使非actor线程在许多方面都可以像Actor一样行事,包括接收消息。
更大的问题是,如果您的线程正在被管理,类似于actor库管理线程的方式,那么表示逻辑上下文的内容可能在某个时间在一个线程上,在另一个时间在另一个线程上。一个很好的例子是servlet容器。您的逻辑上下文可能是一个servlet或会话,但ActorProxy将绑定到线程,因此在逻辑上下文之间共享。如果您的actors没有回复ActorProxy,这不是太大的问题,但如果它们回复了,那么很可能会导致问题,因为(a)回复可能会被错误的上下文接收,或者(b)消息永远不会被接收,因此之前提到的小泄漏变成了一个大泄漏,因为ActorProxies的邮箱被填满。
[编辑] 哎呀...我似乎有阅读问题!将其放在actor块中会创建一个新的actor对象,该对象在终止时将被正确GC。请记住,将消息发送放在actor块中意味着消息发送将在另一个线程上的新反应中完成,而不是在创建actor的线程上完成。

很棒的回答,Eric,谢谢。将调用包装在“actor { }”块中(就像我的问题中那样),是否会遇到同样的问题?或者不管线程是否继续存在,创建的Actor在块退出时都可由GC清除? - oxbow_lakes

0

我认为这样做没有问题。如果在你的代码中有意义,那么为什么不呢? 如果你看一下纯粹的演员模型,每个东西都是一个演员,只有演员之间才会相互通信,如果你能够像这样设计你的代码...太好了...如果你不能或者不想这样做,那么将消息从非演员发送到演员也是可以的。


我不太确定。毕竟,在这个反应中,“sender”是什么? - oxbow_lakes
发送方将成为一个隐式创建的ActorProxy,现在绑定到发送线程。 - Erik Engbrecht

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接