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

Java实现发布-订阅而不使用迭代,java,algorithm,design-patterns,Java,Algorithm,Design Patterns,大多数发布-订阅实现使用某种形式的迭代来通知订阅者,方法是使用for/while循环来调用其侦听器方法,或者将感兴趣的新主题放置在每个订阅者的阻塞队列中 我想实现一个发布-订阅,而不是“监视”某个东西,如位置、变量、文件或其他东西,然后从其存储位置提取新主题。我希望他们都能“大致”同时得到通知 这是因为以前的解决方案很慢,因为我有大量的订阅者,遍历它们需要时间 有什么想法吗?你可以这样做: public class Producer { public static Object publ

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

我想实现一个发布-订阅,而不是“监视”某个东西,如位置、变量、文件或其他东西,然后从其存储位置提取新主题。我希望他们都能“大致”同时得到通知

这是因为以前的解决方案很慢,因为我有大量的订阅者,遍历它们需要时间


有什么想法吗?

你可以这样做:

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;   
            }
        }
    }
}
公共类制作人{
公共静态对象发布对象;
公共静态ConcurrentLinkedQue PreviousObject;
私有整数大小;
公共发布对象(对象){
previousObjects.offerLast(publishedObject);
发布对象=对象;
大小++;
如果(尺寸>50){
previousObjects.removeFirst();
}
}
}
公共类使用者实现可运行{
私有对象lastConsumedObject;
公开募捐{
while(true){
if(Producer.publishedObject==lastConsumedObject){
睡眠(500);
}否则{
迭代器迭代器=Producer.degendingIterator();
Object next=iterator.next();
对象newLastConsumedObject=next;
做{
本流程(下一步);
}while(iterator.hasNext()&&
(next=iterator.next())!=lastConsumedObject);
lastConsumedObject=newLastConsumedObject;
}
}
}
}
其思想是,
生产者
有一个“发布位置”
消费者
可以轮询,并且它还将以前发布的对象存储在
链接列表
中,以防
消费者
没有注意到。使用者轮询发布位置,如果没有更改,则休眠,否则它将处理已发布的对象并遍历以前发布的对象,以防错过发布事件


半忙的等待可能会扼杀你在这里的表现。另一种方法是将消费者分为两类:
SinkConsumer
RelayConsumer
。每个硬件线程将有一个
RelayConsumer
(例如,如果有四个内核和超线程,则有8个
RelayConsumer
)。
Publisher
将消息发布给
RelayConsumers
,然后他们将消息发布给numberOfSinkConsumers/numberOfRelayConsumers
SinkConsumers

您可以执行以下操作:

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;   
            }
        }
    }
}
公共类制作人{
公共静态对象发布对象;
公共静态ConcurrentLinkedQue PreviousObject;
私有整数大小;
公共发布对象(对象){
previousObjects.offerLast(publishedObject);
发布对象=对象;
大小++;
如果(尺寸>50){
previousObjects.removeFirst();
}
}
}
公共类使用者实现可运行{
私有对象lastConsumedObject;
公开募捐{
while(true){
if(Producer.publishedObject==lastConsumedObject){
睡眠(500);
}否则{
迭代器迭代器=Producer.degendingIterator();
Object next=iterator.next();
对象newLastConsumedObject=next;
做{
本流程(下一步);
}while(iterator.hasNext()&&
(next=iterator.next())!=lastConsumedObject);
lastConsumedObject=newLastConsumedObject;
}
}
}
}
其思想是,
生产者
有一个“发布位置”
消费者
可以轮询,并且它还将以前发布的对象存储在
链接列表
中,以防
消费者
没有注意到。使用者轮询发布位置,如果没有更改,则休眠,否则它将处理已发布的对象并遍历以前发布的对象,以防错过发布事件


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

如果问题阻止了修改线程,那么您可能在后台线程中运行notifier循环。查看Akka(或其他行动者框架).问题是迭代,而不是阻塞。谢谢你建议Akka。这是一个学习练习,所以我想在没有库的情况下实现它。我不确定你能用这样的东西获得更好的性能,因为你可以只划分列表并同时迭代订阅服务器。顺便问一下,你有没有检查过任何p发布订阅框架?如果问题是阻止了修改线程,那么您可能在后台线程中运行通知程序循环。看看Akka(或其他参与者框架).问题是迭代,而不是阻塞。谢谢你建议Akka。这是一个学习练习,所以我想在没有库的情况下实现它。我不确定你能用这样的东西获得更好的性能,因为你可以只划分列表并同时迭代订阅服务器。顺便问一下,你有没有检查过任何p发布订阅框架?谢谢。第二个可选的2阶段是我现在拥有的,但它是