Вопрос по java – параллельная модификация arraylist [закрыто]

0

Я создаю многопоточный чат в Java. Когда пользователь u1 отправляет сообщение пользователю u2, но пользователь u2 не подключен, пользователь u1 отправляет сообщение на сервер, и пользователь u2 получит сообщение, как только он подключится к серверу. Сообщения, которые не отправляются, добавляются в 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)

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

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

Ваш Ответ

4   ответа
1

ArrayList api The iterators returned by this class's iterator and listIterator methods are fail-fast: if list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.

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

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();
}

}

3

Вместо этого

pendingmsgs.remove(pendingmsg);

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

itpendingmsgs.remove();

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

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

Из документов Java:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

1

Вместо

pendingmsgs.remove(pendingmsg);

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

itpendingmsgs.remove();

Увидеть:

The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.

Источник:Java API

1

iterator Сам экземпляр. Вы должны позвонитьitpendingmsgs.remove().

Похожие вопросы