Подтвердить что ты не робот

CopyOnWriteArrayList бросает CurrentModificationException

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

... кроме того, что я уже есть.

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

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

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

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

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

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


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: * facepalm *

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

Не знаю наверняка, если это мой преступник, но он проклят подозрительно и нуждается в исправлении независимо.

4b9b3361

Ответ 1

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

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
  }
}

Ответ 2

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