Farouk Alhassan
Farouk Alhassan

Reputation: 3808

Java Implement Publish Subscribe without using Iteration

Most Publish subscribe implementations uses some form of iteration to notify the subscribers either by using a for/while loop to call their listener methods or by placing the new topic of interest on each of them's blocking queue.

I want to implement a publish subscribe that rather "watches" something ie a location, a variable or file or something and then pulls the new topic from its stored location. I want them all to be notified "approximately" at the same time.

This is because the previous solutions are slow because I have a large number of Subscribers and iterating through them takes time.

Any ideas?

Upvotes: 1

Views: 519

Answers (1)

Zim-Zam O'Pootertoot
Zim-Zam O'Pootertoot

Reputation: 18148

You can do something like this:

public class Producer {
    public static Object publishedObject;
    public static ConcurrentLinkedDeque<Object> previousObjects;
    private int size;

    public publishObject(Object object) {
        previousObjects.offerLast(publishedObject);
        publishedObject = object;
        size++;
        if(size > 50) {
            previousObjects.removeFirst();
        }
    }
}

public class Consumer implements Runnable {
    private Object lastConsumedObject;
    public void run() {
        while(true) {
            if(Producer.publishedObject == lastConsumedObject) {
                sleep(500);
            } else {
                Iterator<Object> iterator = Producer.descendingIterator();
                Object next = iterator.next();
                Object newLastConsumedObject = next;
                do {
                    this.process(next);
                } while(iterator.hasNext() && 
                    (next = iterator.next()) != lastConsumedObject);
                lastConsumedObject = newLastConsumedObject;   
            }
        }
    }
}

The idea is that the Producer has a "publish location" that the Consumers can poll, and it also stores previously published objects in a LinkedList in case a Consumer fails to notice one. The Consumer polls the publish location and sleeps if there's been no change, otherwise it processes the published object and iterates through the previously published objects in case it missed a publish event.

The semi-busy waiting might kill your performance here. An alternative is to have two classes of consumer: SinkConsumer and RelayConsumer. You would have one RelayConsumer per hardware thread (e.g. 8 RelayConsumers if you have four cores and hyperthreading). The Publisher publishes the message to the RelayConsumers, who then each publish the message to numberOfSinkConsumers/numberOfRelayConsumers SinkConsumers.

Upvotes: 1

Related Questions