2013-10-27 5 views
3

Я следующий кодСписок 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) at java.util.AbstractList $ Itr.next (AbstractList.java:420)

Как решить эту проблему с использованием следующего или с помощью итератора?

Edit 1

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

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

      myDAO.saveProjects(projectList); 

    } 
    projectList.clear(); 
+0

Не уверен в причинах понижения голосов. Это законный и полный вопрос. 1+ –

+0

Я беру это обратно. Опечатка была отвлекающей и вводящей в заблуждение. –

+0

@HovercraftFullOfEels Спасибо – user75ponic

ответ

6

из кода

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); 
+0

Максим. Если я удалю для цикла из второго, то он прекратит сохранение записей. – user75ponic

+0

Если вы введете 'insertProjects (listItems);' вы все еще получаете эту ошибку? –

+0

Вы имеете в виду непосредственно вызов 'insertProjects (listItems);'? – user75ponic

1

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

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

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

+0

С чем связаны нити? –

+0

Это комментарий в лучшем случае (как вы уже сделали), а не ответ. –

Смежные вопросы