Почему я получаю ConcurrentModificationException, даже используя итератор? - PullRequest
0 голосов
/ 11 мая 2018

У меня есть 3 сервера и клиент, отправляющий сообщения.И я реализую алгоритм BFT.Итак, у меня есть эта часть кода

    int tam = 0;

    if (unordered.size() <= maxOrderSize) {
        tam = unordered.size();
    } else {
        tam = maxOrderSize;
    }
    HashMap<String, byte[]> prop = new HashMap<String, byte[]>(tam);

    Iterator<String> it = unordered.keySet().iterator();

    for (int i = 0; i < tam; i++) {
        if (it.hasNext()) {
            String id = it.next();
            prop.put(id, unordered.get(id));
            it.remove();
            unordered.remove(id);

        }
    }

, и во время выполнения объекты импортируются и удаляются с моей карты неупорядоченные .Также я хочу упомянуть, что неупорядоченный определяется:

    Map<String, byte[]> unordered = Collections.synchronizedMap(new HashMap<String, byte[]>());

Но вдруг он создает это исключение:

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.remove(HashMap.java:1456)
at edu.bft.comm.layer.BatchControl.createOrderMessage(BatchControl.java:123)
at edu.bft.comm.layer.BatchControlTPM.run(BatchControlTPM.java:24)

Есть идеи, почему это происходит?

EDIT1: Я пытался удалить эту строку: unordered.remove (id);

, и я получил эту ошибку:

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
at java.util.HashMap$KeyIterator.next(HashMap.java:1466)
at edu.bft.comm.layer.BatchControl.createOrderMessage(BatchControl.java:120)
at edu.bft.comm.layer.BatchControlTPM.run(BatchControlTPM.java:24)

EDIT2: Также яхочу упомянуть, что, хотя я итерирую неупорядоченный , некоторые новые объекты могут добавляться, в то время как новые сообщения приходят от клиента.

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

ОК, после Edit2 я чувствую, что другой ответ имеет смысл.

Прежде всего: если у вас есть стандартная HashMap, она по умолчанию не является поточно-ориентированной!Поэтому итерации по такой коллекции всегда могут вызвать проблемы, если другие потоки одновременно изменяют ее.Возможно, добавление новых элементов не вызовет исключение, может быть.

Если у вас есть возможность изменить реализацию Map на unordered, используйте что-нибудь поточно-безопасное, например ConcurrentHashMap .В этом случае не возникнет никаких проблем, если кто-то изменит его, в то время как другой поток перебирает свои элементы с помощью итератора - итератор имеет свою собственную коллекцию элементов, которые не будут напрямую мешать исходной карте.

Если вы не можете изменить реализацию, у вас проблемы ...

0 голосов
/ 11 мая 2018

Это именно то, что ConcurrentModificationException предотвращено:

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

Как правило, вы не можете изменять коллекцию, когда итератор выполняет итерацию. См. SO ответ и этот .

0 голосов
/ 11 мая 2018

Вы сами модифицируете Карту.

Удалите эту строку: unordered.remove(id);

При редактировании вы модифицируете Карту, повторяя ее, поэтому очевидно, что это проблема.

В документ сказано:

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

И HashMap выдает ConcurrentModificationException каквы видите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...