Гуава MultiMap и ConcurrentModificationException [дубликат]

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

Не тестируемый некоторая обработка ошибок. В каждом коде существует обработка ошибок, которая никогда не может происходить. Например, в Java должна быть выгода многие исключение, потому что это - часть интерфейса. Но используемый экземпляр никогда не будет бросать его. Или случай по умолчанию переключателя, если для всех возможных случаев блок случая существует.

, Конечно, часть не нужной обработки ошибок может быть удалена. Но есть ли ошибка кодирования в будущем тогда, это плохо.

9
задан Ashwin Krishnamurthy 11 June 2014 в 13:51
поделиться

3 ответа

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

Изменить: изменить ваш пример:

Iterator<Map.Entry<GenericEvent, Command>> i = eventMultiMap.entries().iterator();
while (i.hasNext()) {
    if (i.next().getValue().equals(command)) {
        i.remove();
        nbRemoved++;
    }
}
11
ответ дан 4 December 2019 в 09:13
поделиться

Если другой поток может изменить вашу мульти-карту во время работы этой логики, вам нужно будет добавить синхронизированный блок в код MHarris:

synchronized (eventMultimap) {
  Iterator<Entry<GenericEvent, Command>> i = eventMultiMap.entries.iterator();
  while (i.hasNext()) {
    if (i.next().getValue().equals(command)) {
        i.remove();
        nbRemoved++;
    }
  }
}

Или вы можете опустить итератор как следует,

synchronized (eventMultimap) {
  int oldSize = eventMultimap.size();
  eventMultimap.values().removeAll(Collections.singleton(command));
  nbRemoved = oldSize - eventMultimap.size();
}

Вызов removeAll () не требует синхронизации. Однако, если вы опустите синхронизированный блок, multimap может мутировать между вызовом removeAll () и одним из вызовов size (), что приведет к неправильному значению nbRemoved.

Теперь, если ваш код однопоточный, и вы просто хотите избежать вызова ConcurrentModificationException, вы можете опустить Multimaps.synchronizedMultimap и синхронизированную логику (eventMultimap).

synchronized (eventMultimap) {
  int oldSize = eventMultimap.size();
  eventMultimap.values().removeAll(Collections.singleton(command));
  nbRemoved = oldSize - eventMultimap.size();
}

Вызов removeAll () не требует синхронизации. Однако, если вы опустите синхронизированный блок, multimap может мутировать между вызовом removeAll () и одним из вызовов size (), что приведет к неправильному значению nbRemoved.

Теперь, если ваш код однопоточный, и вы просто хотите избежать вызова ConcurrentModificationException, вы можете опустить Multimaps.synchronizedMultimap и синхронизированную логику (eventMultimap).

synchronized (eventMultimap) {
  int oldSize = eventMultimap.size();
  eventMultimap.values().removeAll(Collections.singleton(command));
  nbRemoved = oldSize - eventMultimap.size();
}

Вызов removeAll () не требует синхронизации. Однако, если вы опустите синхронизированный блок, multimap может мутировать между вызовом removeAll () и одним из вызовов size (), что приведет к неправильному значению nbRemoved.

Теперь, если ваш код однопоточный, и вы просто хотите избежать вызова ConcurrentModificationException, вы можете опустить Multimaps.synchronizedMultimap и синхронизированную логику (eventMultimap).

4
ответ дан 4 December 2019 в 09:13
поделиться

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

5
ответ дан 4 December 2019 в 09:13
поделиться
Другие вопросы по тегам:

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