我有一个可观察的,通知所有注册观察员。
public void notifyObservers(T message) {
notifying = true;
for (Observer<T> observer : observers)
observer.notify(message);
notifying= false;
}
我的可观察类中也有这个方法:
public void removeObserver(final Observer<T> observer){
if (!this.observers.contains(observer))
return;
if (!notifying) {
this.observers.remove(observer);
return;
}
final ArrayList<Observer<T>> observerList = this.observers;
new Thread(new Runnable() {
public void run() {
while (notifying);
observerList.remove(observer);
}
}).start();
}
为了确保在通知期间没有进行删除呼叫,我在新线程中等待通知完成。但是,其中一个添加的Observers正在调用它在removeObserver
- 方法中添加的observable的notify
- 方法,并且在ArrayList的removecall行中得到一个ArrayIndexOutOfBoundsException: p>
Exception in thread "Thread-4" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.fastRemove(Unknown Source)
at java.util.ArrayList.remove(Unknown Source)
at allgemeines.Observable$2.run(Observable.java:96)
at java.lang.Thread.run(Unknown Source)
为什么会发生这种情况?
答案 0 :(得分:2)
为什么不使用带有synchronized的锁定,而不是使用通知布尔值?类似的东西:
public void notifyObservers(T message) {
synchronized(observers) {
for (Observer<T> observer : observers)
observer.notify(message);
}
...
public void removeObserver(final Observer<T> observer){
synchronized(this.observers) {
final ArrayList<Observer<T>> observerList = this.observers;
observerList.remove(observer);
}
}
答案 1 :(得分:1)
您的代码不是线程安全的。 尝试通过remove和notify方法中的synchronized同步锁定观察者。
答案 2 :(得分:1)
解决了!好吧,我无法弄清楚为什么在上面的问题中我的例子中抛出了异常,但我找到了一种方法来重写有效的方法。我将列表转换为数组并迭代该数组而不是列表,这是一个属性:
@SuppressWarnings("unchecked")
public synchronized void notifyObservers(T message) {
Object[] observerArray = observers.toArray();
for (Object observer : observerArray)
((Observer<T>) observer).notify(message);
}
add
和remove
方法现在非常简单(只需将方法调用委托给ArrayList
- 方法:
public void addObserver(Observer<T> observer){
this.observers.add(observer);
}
public void removeObserver(Observer<T> observer) {
this.observers.remove(observer);
}
知道为什么我的第一个解决方案不起作用仍然很有趣。