而不是对 Actor 进行静态引用(WebSocketRouter
在你的情况下),为什么不想出一些消息来发送它呢?这样,参与者就可以以一致的方式维护自己的内部状态。通过消息进行状态更改是 Actor 模型的主要好处之一。
在开始编写代码之前,如果这不是 100% 准确,我很抱歉,我只使用了 Akka 的 Scala 版本,并且基于对 Akka 的快速扫描Akka 文档 http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html.
所以在你的例子中,我会定义一些对象来表达加入/离开......
public class JoinMessage { }
public class ExitMessage { }
注意ExitMessage
仅当您打算保持 WebSocket 打开并让用户停止侦听路由器时才需要。否则,路由器可以检测到 Actor 何时被终止。
然后你会改变你的MessageSender
演员在加入或离开聊天室时发送这些消息......
public class MessageSender extends UntypedActor {
public static Props props(ActorRef out) {
return Props.create(MessageSender.class, out);
}
private final ActorRef out;
private final ActorRef router;
public MessageSender(ActorRef out) {
this.out = out;
this.router= getContext().actorSelection("/Path/To/WebSocketRouter");
}
@Override
public void preStart() {
router.tell(new JoinMessage(), getSelf());
}
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
out.tell(message, getSelf());
} else {
unhandled(message);
}
}
}
然后你的路由器可以更改为在内部管理状态,而不是在 Actor 上公开内部方法(正如你所知,这不好)......
public class WebSocketRouter extends UntypedActor {
private final Set<ActorRef> senders = new HashSet<>();
private void addSender(ActorRef actorRef){
senders.add(actorRef);
}
private void removeSender(ActorRef actorRef){
senders.remove(actorRef);
}
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof JoinMessage) {
addSender(sender);
getContext().watch(sender); // Watch sender so we can detect when they die.
} else if (message instanceof Terminated) {
// One of our watched senders has died.
removeSender(sender);
} else if (message instanceof String) {
for (ActorRef sender : senders) {
sender.tell(message, getSelf());
}
}
}
}
同样,此代码旨在让您了解如何利用 Actor 模型来完成此任务。抱歉,如果 Java 不是 100% 准确,但希望您能遵循我的意图。