CopyOnWriteArrayList выбрасывает CurrentModificationException - PullRequest
14 голосов
/ 06 октября 2009

Иногда я получаю ConcurrentModificationException, когда перебираю список. Поиск Google сообщает мне, что это, вероятно, потому, что я изменяю этот список в другом потоке, перебирая его, и что, чтобы устранить эту проблему, я должен использовать java.util.concurrent.CopyOnWriteArrayList ....

... кроме меня уже.

Очевидно, я делаю что-то действительно где-то глупо.

Есть ли у кого-нибудь понимание того, как можно заставить CopyOnWriteArrayList бросить ConcurrentModificationException? Если это имеет значение, я использую Java 5.

Редактировать: Поскольку используемые мутаторы могут иметь значение, я изменяю этот список двумя способами:

  • Добавление элементов спереди. (list.add(0, newElement);) * * тысяча двадцать-одна
  • Использование подсписка, чтобы старые предметы падали со спины. (list = list.subList(0, MAX_LIST_SIZE);)

Они поднимают красные флаги? Если так, то почему? Насколько я понимаю, поскольку эти операции сначала копируют объект, любые существующие итераторы будут указывать на неизмененный оригинал и, следовательно, не будут заботиться об этом. У меня есть дыра в моих знаниях?

Редактировать 2: Точный код, который вызывает проблему, все еще немного неясен, но я могу по крайней мере опубликовать исключение, которое я вижу:

<code>
java.util.ConcurrentModificationException
    at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(Unknown Source)
    at java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(Unknown Source)
    at....

... где это указывает на создание цикла для каждого в моем коде.

То, что COWSubList, похоже, подразумевает, что мой вызов subList является корнем моей проблемы; Я все еще хотел бы понять, почему.

Редактировать 3: * лицевая панель *

CopyOnWriteArrayList.subList() возвращает List, не a CopyOnWriteArrayList. Список, который он возвращает, не подразумевает никаких обязательств по обеспечению какой-либо защиты COWAL. Что делает использование subList() подобным образом для удаления элементов очень плохой идеей.

Не знаю наверняка, является ли это моим виновником, но это чертовски подозрительно и требует исправления независимо от *. 1055 *

Ответы [ 2 ]

18 голосов
/ 06 октября 2009

CopyOnWriteArrayList.subLists генерирует исключения ConcurrentModificationException, если содержащийся список изменяется из-под него:

public class ListTest {

  private static List<int[]> intList;

  public static void main (String[] args) {
    CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
    cowal.add(1);
    cowal.add(2);
    cowal.add(3);

    List<Integer> sub = cowal.subList(1, 2);
    cowal.add(4);
    sub.get(0); //throws ConcurrentModificationException
  }
}
0 голосов
/ 07 октября 2009

Sbodd имеет правильный ответ, но похоже, что использование CopyOnWriteArrayList вместо ArrayList является просто попыткой замаскировать ошибку. Истинная проблема - попытка изменить базовый список, перебирая его. Вам нужно найти, где в вашем коде вы обращаетесь к нему как таковому, и удалить это использование или обойти его.

...