Список ConcurrentModificationException

У меня есть следующий код

public void saveProjects(List<Project> proj) throws DatabaseException {
    for (Project listItems: proj) { // error here

        insertProjects(listItems);
    }
}

private void insertProjects(Project prj) throws DatabaseException {
    commitObjects(prj);
}

Когда я выполняю вышеуказанное, я получаю следующее исключение на for (Project listItems: proj) {

java.util.ConcurrentModificationException в java.util.AbstractList $ Itr.checkForComodification (AbstractList.java:449) в java.util.AbstractList $ Itr.next (AbstractList.java:420)

Как решить эту проблему с помощью next или итератора?

Редактировать 1

Фрагмент кода, в котором я вызываю saveProjects

projectList.add(proj);
  for (Project persist: projectList) {
       persist.setProjectId("K7890");
       persist.setName(fileName);

          myDAO.saveProjects(projectList);

     }
  projectList.clear();

person Jacob    schedule 27.10.2013    source источник
comment
Не уверен в причинах голосов против. Это законный и полный вопрос. 1+   -  person Hovercraft Full Of Eels    schedule 27.10.2013
comment
Я беру это обратно. Опечатка отвлекала и вводила в заблуждение.   -  person Hovercraft Full Of Eels    schedule 28.10.2013
comment
@HovercraftFullOfEels Спасибо   -  person Jacob    schedule 28.10.2013
comment
Что делает commitObjects(prj)? Это как-то модифицирует List<Project> proj?   -  person Hovercraft Full Of Eels    schedule 28.10.2013
comment
@HovercraftFullOfEels Я включил фрагмент кода метода commitObjects.   -  person Jacob    schedule 28.10.2013
comment
Что такое callablestatement тип?   -  person Maxim Shoustin    schedule 28.10.2013
comment
@MaximShoustin callablestatement - тип подключения к базе данных.   -  person Jacob    schedule 28.10.2013
comment
Можете ли вы разместить код там, где вы звоните saveProjects?   -  person Maxim Shoustin    schedule 28.10.2013
comment
Странно, не похоже, что вы где-то меняли список. Можете ли вы попробовать обернуть список Collections.unmodifiableList(...) перед повторением по нему? Вы вызываете что-то одновременно?   -  person Ortwin Angermeier    schedule 28.10.2013
comment
Почему ты дважды пробежал projectList. 1-й цикл for (Project persist: projectList) { и после того, как вы снова запустите saveProjects   -  person Maxim Shoustin    schedule 28.10.2013
comment
@MaximShoustin Это вызывает исключение? Если да, то какой для этого лучший подход?   -  person Jacob    schedule 28.10.2013
comment
Еще немного вашей трассировки стека, показывающей, где в коде в коде могут быть полезны эти строки.   -  person Peter Lawrey    schedule 28.10.2013


Ответы (2)


Из кода

for (Project persist: projectList) { 
     persist.setProjectId("K7890");
     persist.setName(fileName);

      myDAO.saveProjects(projectList); 
 }

projectList.clear(); // <-- clear might cause to this Exception

Справка

Почему при использовании итератора возникает исключение ConcurrentModificationException?

Классы java.util Collection работают без сбоев, что означает, что если один поток изменяет коллекцию, в то время как другой поток просматривает ее с помощью итератора, вызов iterator.hasNext() или iterator.next() вызовет ConcurrentModificationException.

Даже классы-оболочки синхронизированной коллекции SynchronizedMap и SynchronizedList являются только условно-поточно-ориентированными, что означает, что все отдельные операции являются поточно-ориентированными, но составные операции, в которых поток управления зависит от результатов предыдущих операций, могут быть связаны с проблемами многопоточности. (List myList = Collections.synchronizedList (myList)! Здесь может не работать)

Решения для ситуаций с многопоточным доступом

Решение 1. Вы можете преобразовать свой список в массив с помощью list.toArray() и выполнить итерацию по массиву. Этот подход не рекомендуется, если список большой.

Решение 2. Вы можете заблокировать весь список во время итерации, заключив код в синхронизированный блок. Этот подход отрицательно сказывается на масштабируемости вашего приложения, если оно очень параллельно.

Решение 3. Вы можете использовать классы ConcurrentHashMap и CopyOnWriteArrayList, которые обеспечивают гораздо лучшую масштабируемость, а итератор, возвращаемый ConcurrentHashMap.iterator(), не будет генерировать ConcurrentModificationException при сохранении безопасности потоков.

Решение для ситуации с однопоточным доступом

Использовать:

it.remove();

Он удаляет текущий объект через итератор it, который ссылается на вашу базовую коллекцию list.

Избегать:

list.remove(myObject);
person Maxim Shoustin    schedule 27.10.2013
comment
Максим, если убрать цикл for со второго, то он перестанет сохранять записи. - person Jacob; 28.10.2013
comment
Если вы зафиксируете insertProjects(listItems);, вы все равно получите эту ошибку? - person Maxim Shoustin; 28.10.2013
comment
Вы имеете в виду прямой вызов insertProjects(listItems);? - person Jacob; 28.10.2013
comment
переключить комментарий, например // insertProjects (listItems); Может соединение что-то делает. Я не знаком с логикой доступа к данным - person Maxim Shoustin; 28.10.2013
comment
Когда я комментирую insertProjects(listItems);, исключений нет. - person Jacob; 28.10.2013
comment
Кстати, попробуйте прокомментировать projectList.clear(); Взгляните на этот пост: stackoverflow.com/questions/17899738/ - person Maxim Shoustin; 28.10.2013
comment
Извините, даже после комментария insertProjects(listItems); он выдает исключение. - person Jacob; 28.10.2013
comment
Да, удаление projectList.clear() решает проблему. У меня есть вопрос, нужно ли нам очищать список после его использования? - person Jacob; 28.10.2013

Выглядит странно, я предполагаю, что вы изменяете список (List<Project> proj) в другом потоке во время итерации по нему?

Потому что вы никоим образом не изменяете список в коде, который вы нам дали.

Вы можете попробовать вызвать метод saveProjects с копией списка proj.

person Ortwin Angermeier    schedule 27.10.2013
comment
В лучшем случае это комментарий (как вы уже сделали), а не ответ. - person Jeroen Vannevel; 28.10.2013