2012-05-21 2 views
0

Я создаю многопоточный чат в java. Когда пользователь u1 отправляет сообщение пользователю u2, но пользователь u2 не подключен, пользователь u1 отправляет сообщение на сервер, а пользователь u2 будет получать сообщение после его подключения к серверу. Сообщения, которые не отправляются, добавляются в ArrayList. Как только пользователь подключается, он проверяет, является ли он получателем ожидающего сообщения. Если он есть, сообщение отправляется ему, а затем удаляется из списка ожидающих сообщений. Вот как я это делаю:одновременная модификация arraylist

for(Iterator<String> itpendingmsgs = pendingmsgs.iterator(); itpendingmsgs.hasNext();) { 
    String pendingmsg = itpendingmsgs.next(); 
    String dest = pendingmsg.substring(4);    
    if (protocol.author.equals(dest)) { 
     sendMsg(msg); 
     pendingmsgs.remove(pendingmsg); 
    } 
} 

это то, что я получаю:

Exception in thread "Thread-3" java.util.ConcurrentModificationException 
at java.util.AbstractList$Itr.checkForComodification(Unknown Source) 
at java.util.AbstractList$Itr.next(Unknown Source) 
at ChatServer$ClientConnection.run(ChatServer.java:383) 
at java.lang.Thread.run(Unknown Source) 

Как я могу это исправить? Это потому, что я использую итератор?

+0

Вы не можете использовать удалить в то время как итерация – keyser

ответ

3

Вместо этого

pendingmsgs.remove(pendingmsg); 

использования

itpendingmsgs.remove(); 

Iterator из ArrayList является fail fast, так что пока вы итерацию над ArrayList использованием Iterator, если лежащий в основе ArrayList модифицирована любым другим способом, чем add и remove предоставленных Iterator сам он бросит ConcurrentModificationException и выручит.

В текущей реализации в то время как вы пробегаем по списку на определенном состоянии вы также модифицирующих список вызвав remove на подстилающей ArrayList, а называют remove метод Iterator.

Из Java Docs:

Итераторы, возвращаемые итератора этого класса и ListIterator методы отказоустойчивость быстро: если список конструктивно изменен в любое время после того, как итератор создается, в любом случае кроме как через собственные методы удаления или добавления итератора, итератор будет вызывать ConcurrentModificationException. Таким образом, несмотря на одновременную модификацию , итератор не работает быстро и чисто, а не , рискуя произвольным, недетерминированным поведением в неопределенное время в будущем.

Обратите внимание, что неэффективное поведение итератора не может быть гарантировано , поскольку, как правило, невозможно сделать какие-либо жесткие гарантии при наличии несинхронизированной параллельной модификации. Fail-fast Итераторы бросают ConcurrentModificationException с наилучшим усилием . Поэтому было бы неправильно писать программу, которая зависела от от этого исключения за ее правильность: неудачное поведение итераторов должно использоваться только для обнаружения ошибок.

1

Вам не разрешается изменять список при повторении через него, за исключением самого экземпляра iterator. Вы должны позвонить itpendingmsgs.remove().

1

Вместо

pendingmsgs.remove(pendingmsg); 

использования

itpendingmsgs.remove(); 

См:

Поведение итератора не определен, если лежащий в основе набор изменяется в то время как итерации в ходе любым способом , кроме как путем вызова этого метода.

Источник: Java API

1

На основании документации отказоустойчивость быстро ArrayList apiИтераторов, возвращаемых итераторы и ListIterator методов этого класса: если список конструктивно изменен в любое время после того, как создаются итератор, в любом за исключением собственных методов удаления или добавления итератора, итератор будет вызывать исключение ConcurrentModificationException.

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

for(Iterator<String> itpendingmsgs = pendingmsgs.iterator(); itpendingmsgs.hasNext();) { 
String pendingmsg = itpendingmsgs.next(); 
String dest = pendingmsg.substring(4);    
if (protocol.author.equals(dest)) { 
    sendMsg(msg); 
    itpendingmsgs.remove(); 
} 

}

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