0

I have a number of concurrent clients - i.e. threads running and doing something concurrently. Each client implements a listener of some event bus. A message from that bus can arrive to one or more clients. My task is to broadcast that message to all the clients.

This task seems simple, but I cannot find a solution which is not ugly in some way.

(1) The straightforward solution:

void onMessageArrived(Message message) {
   broadcast(message);
}
  • is bad because each message will be broadcasted for many times because several clients can receive that message, and thus several onMessageArrived handlers can run.

(2) We can store the broadcasted messages in some list:

void onMessageArrived(Message message) {
 if (alreadyBroadcastedConcurrentMap.putIfAbsent(message)==null) {
     broadcast(message);
 }
}
  • this solves the previously mentioned problem, but many clients will repeat the useless operation of putting the already existing message into that list.

But may be there are some better options?

Java.

KutaBeach
  • 1,445
  • 21
  • 43

2 Answers2

1

The problem lies with the fact that you receive multiple messages in the first place. In theory, if you should get 5 requests to broadcast, then 5 broadcasts should take place by the way your event system works. Simply put, if that is not what you want, then you should not use this pattern.

If receiving multiple messages is not something you can control, then at the least, the receiver passing messages should note repeated messages and disregard them rather than passing them onto other threads.

In short, the thread only does what it is told. It should not have to worry about the state of another thread, so you should either switch patterns or intercept the message prior to passing it on to your threads.

Neil
  • 5,762
  • 24
  • 36
0

Your design contains flaws, or it is badly explained. Either you want to broadcast to all clients, or multicast to a selected list. It doesn't make sense to specify some recipients and then make each recipient responsible for delivering it to all the other clients, handling duplications and races by hand. Just make all clients listening to the bus, possibly ignoring messages.

I'd introduce a new central Broadcaster

public class Broadcaster {

  List<Client> clients;

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

Obviously each client will have to register to this broadcast domain

public class Client {

  private Broadcaster broadcaster;

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

}

and just forget about multiple delivery. You can go further and simulate a LAN by using multiple broadcast domains, if the number of clients is huge and you have other very strict requirements - which I don't think you have

Raffaele
  • 20,627
  • 6
  • 47
  • 86
  • 1
    Raffaele, actually I have a number of chats, and an admin, which command should be broadcasted to all the chats. I wanted to catch the moment when that command arrives to his chat and then broadcast to the chats where he is absent. Thats why I asked. But you and Neil said it right, its better to change the architecture. I will send admin messages as internal commands, without listening for them in chat at all. Thanks! – KutaBeach Sep 25 '12 at 07:50