如何在并发客户端之间广播消息?

时间:2012-09-24 12:45:49

标签: java concurrency broadcast broadcasting

我有许多并发客户端 - 即线程正在运行并同时执行某些操作。 每个客户端实现一些事件总线的监听器。 来自该总线的消息可以到达一个或多个客户端。 我的任务是向所有客户广播该消息。

这项任务看起来很简单,但我找不到一种在某种程度上并不丑陋的解决方案。

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

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

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

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

但可能有更好的选择吗?

爪哇。

2 个答案:

答案 0 :(得分:1)

问题在于您首先收到多条消息。从理论上讲,如果您应该收到5个广播请求,那么应该通过事件系统的工作方式进行5次广播。简单地说,如果那不是您想要的,那么您就不应该使用这种模式。

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

简而言之,线程只会按照它所说的去做。它不应该担心另一个线程的状态,因此您应该在将消息传递给线程之前切换模式或拦截消息。

答案 1 :(得分: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);
  }

}

忘了多次送货。你可以通过使用多个广播域来进一步模拟局域网,如果客户端数量巨大且你有其他非常严格的要求 - 我认为你没有