【问题标题】:Order of Observer notification with notifyObservers()使用 notifyObservers() 通知观察者的顺序
【发布时间】:2017-07-12 09:29:27
【问题描述】:

我有以下代码:

public class MyObservable extends Observable {
    // ...
    public void doSomething() {
        // do stuff
        setChanged();
        notifyObservers();
    }
}

public class A implements Observer {
    public void update(Observable o, Object arg) {
        // do something
    }
}

public class B implements Observer {
    public void update(Observable o, Object arg) {
        // do something
    }
}

以及主要功能:

public static void main(String[] args) {
    MyOvervable a = new MyObservable();
    a.addObserver(new A());
    a.addOberser(new B());
    a.doSomething();
}

notifyObservers() 调用更新函数的顺序是否与我使用 addObserver() 添加观察者的顺序相同?

【问题讨论】:

标签: java observer-pattern


【解决方案1】:

Observable 的 Javadoc 表示通知是按照监听器注册的顺序进行的,但这是不正确的 - 通知实际上是按 reverse order 发出的。

带有解释性 cmets 的代码摘录:

// addObserver() adds last-most at end of the list
public synchronized void addObserver(Observer o) {
    ..
    obs.addElement(o);
}

public void notifyObservers(Object arg) {
    ..
    // notifyObservers iterates backwards; last-most first.
    for (int i = arrLocal.length-1; i>=0; i--)
        ((Observer)arrLocal[i]).update(this, arg);
}

我提交了一个错误报告——https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8214760——但是由于 Observable 已被弃用,它已被关闭,因为“不会修复”。

我的信念是,所实施的行为是稳定的,不会改变;更改顺序可能会破坏许多使用此顺序的应用程序的兼容性。

【讨论】:

    【解决方案2】:

    是的。这是 java java.util.Observable 类的摘录。

    private Vector<Observer> obs;
    
    arrLocal = obs.toArray();
    
    for (int i = arrLocal.length-1; i>=0; i--)
        ((Observer)arrLocal[i]).update(this, arg);
    

    Vector 基于索引并由内部数组备份。 Vector 维护元素的插入顺序。意味着您可以假设如果您遍历 Vector,您将按照插入的顺序获取对象。

    所以你的问题的答案是:YES

    【讨论】:

    • 不正确。插入顺序是向前的,但循环向后迭代 - 所以整体顺序与预期和记录的相反。请参阅下面的答案。
    【解决方案3】:

    根据甲骨文的docs

    未指定发送通知的顺序。 Observable 类中提供的默认实现将按照它们注册感兴趣的顺序通知观察者,但子类可能会更改此顺序,使用不保证顺序,在单独的线程上传递通知,或者可以保证它们的子类遵循此顺序,因为它们选择。

    【讨论】:

    • Javadoc 不正确,错误报告已被接受——请参阅下面的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多