0

我有许多并发客户端——即线程同时运行和做某事。每个客户端都实现了某个事件总线的侦听器。来自该总线的消息可以到达一个或多个客户端。我的任务是将该消息广播给所有客户。

这个任务看起来很简单,但我找不到在某种程度上不难看的解决方案。

(1) 直截了当的解决方案:

void onMessageArrived(Message message) {
   broadcast(message);
}
  • 不好,因为每条消息都会被广播多次,因为多个客户端可以接收该消息,因此可以运行多个 onMessageArrived 处理程序。

(2) 我们可以将广播的消息存储在某个列表中:

void onMessageArrived(Message message) {
 if (alreadyBroadcastedConcurrentMap.putIfAbsent(message)==null) {
     broadcast(message);
 }
}
  • 这解决了前面提到的问题,但是许多客户端会重复将已经存在的消息放入该列表的无用操作。

但是可能有更好的选择吗?

爪哇。

4

2 回答 2

1

问题在于您首先会收到多条消息。理论上,如果您应该收到 5 个广播请求,那么按照您的事件系统的工作方式应该会发生 5 个广播。简单地说,如果这不是你想要的,那么你不应该使用这种模式。

如果接收多条消息不是您可以控制的,那么至少,传递消息的接收者应该注意重复的消息并忽略它们,而不是将它们传递给其他线程。

简而言之,线程只做它被告知的事情。它不必担心另一个线程的状态,因此您应该在将消息传递给您的线程之前切换模式或拦截消息。

于 2012-09-24T12:52:10.720 回答
0

您的设计包含缺陷,或者解释不当。您想向所有客户端广播,或向选定列表多播。指定一些收件人然后让每个收件人负责将其交付给所有其他客户端,手动处理重复和竞争是没有意义的。只需让所有客户端都听总线,可能会忽略消息。

我会介绍一个新的中央Broadcaster

public class Broadcaster {

  List<Client> clients;

  public void broadcast(Message msg) {
    for (Client client: clients)
      if (!msg.from().equals(client))
        msg.send(client);
  }
}

显然每个客户端都必须注册到这个广播域

public class Client {

  private Broadcaster broadcaster;

  public void join(Broadcaster broadcaster) {
    this.broadcaster = broadcaster;
    broadcaster.announce(this);
  }

}

并且忘记多次交付。如果客户端数量很大并且您有其他非常严格的要求 - 我认为您没有,您可以更进一步并使用多个广播域来模拟 LAN

于 2012-09-24T18:05:27.213 回答