2016-08-26 4 views
1

Ниже приведен код, я получаю ConcurrentModificationException в вызове subiter.next(), хотя я не изменяю базовую коллекцию и ее работу как один поток.Почему этот код генерирует исключение ConcurrentModificationException?

Tree tree=partition.getTreeofThisPartition(); 
Set<DzExpressionHostTupel> oldSubtupels=tree.getSubscribers(); 
Iterator<DzExpressionHostTupel> subiter=oldSubtupels.iterator();   
while (subiter.hasNext()){ 
    DzExpressionHostTupel subtupel=subiter.next(); 
    tree.removeSubscriber(subtupel); 
} 
+1

Возможный дубликат http://stackoverflow.com/questions/1655362/concurrentmodificationexception-despite-using-synchronized – NageN

+0

вы должны использовать метод 'subiter.remove()' вместо 'tree.removeSubscriber (subtupel)'. – NageN

+0

Мне нужно удалить элемент из существующего дерева, где он был добавлен до этого, iterator.remove() не сделает этого. –

ответ

5

Если вы читали https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html, он говорит:

Например, это вообще не допустимо для одного потока для изменения коллекции, а другой поток итерации над ним. В общем случае результаты итерации в этих условиях не определены. Некоторые реализации Iterator (в том числе и для всех реализаций коллекции общего назначения, предоставляемых JRE) могут выбрать выброс этого исключения, если это обнаружено. Итераторы, которые делают это, известны как отказоустойчивые итераторы, поскольку они терпят неудачу быстро и чисто, а скорее рискуют произвольным, недетерминированным поведением в неопределенное время в будущем.

Обратите внимание, что это исключение не всегда указывает, что объект был одновременно изменен другим потоком. Если один поток выдает последовательность вызовов методов, которые нарушают договор объекта, объект может вызывать это исключение. Например, если поток изменяет коллекцию напрямую, когда он выполняет итерацию по коллекции с быстрым итератором, итератор выкинет это исключение.

(выделено мной).

Я предполагаю, что tree.removeSubscriber(subtupel); изменяет его набор subscribers.

+2

У него нет двух потоков, но он чередует модификацию структуры данных во время итерации. –

+1

Да, обратитесь к части javadoc, выделенной полужирным шрифтом. – Taylor