Java实现发布订阅而不使用迭代

时间:2013-08-14 10:12:49

标签: java algorithm design-patterns

大多数发布订阅实现使用某种形式的迭代通过使用for / while循环来调用其侦听器方法或通过将新感兴趣的主题放置在每个阻塞队列上来通知订阅者。

我想实现一个发布订阅,而不是“监视”某些东西,即位置,变量或文件或其他内容,然后从其存储位置提取新主题。我希望所有人都能同时“大约”收到通知。

这是因为之前的解决方案很慢,因为我有大量订阅者并且通过它们进行迭代需要时间。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您可以这样做:

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;   
            }
        }
    }
}

我的想法是Producer有一个Consumers可以轮询的“发布位置”,如果LinkedList,它还会将以前发布的对象存储在Consumer中没有注意到一个。消费者轮询发布位置并在没有变化时休眠,否则它处理发布的对象并迭代先前发布的对象,以防它错过发布事件。

半繁忙的等待可能会在这里扼杀你的表现。另一种方法是拥有两类消费者:SinkConsumerRelayConsumer。每个硬件线程只有一个RelayConsumer(例如,如果您有四个核心和超线程,则为RelayConsumers)。 Publisher将消息发布到RelayConsumers,然后每个人都将消息发布到numberOfSinkConsumers / numberOfRelayConsumers SinkConsumers