ArrayList.remove(Object)抛出一个ArrayIndexOutOfBoundsException:-1

时间:2015-09-11 06:43:22

标签: java arraylist

我有一个可观察的,通知所有注册观察员。

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)

为什么会发生这种情况?

3 个答案:

答案 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);
}

addremove方法现在非常简单(只需将方法调用委托给ArrayList - 方法:

public void addObserver(Observer<T> observer){
    this.observers.add(observer);
}

public void removeObserver(Observer<T> observer) {
    this.observers.remove(observer);
}

知道为什么我的第一个解决方案不起作用仍然很有趣。