Что такое ConcurrentModificationException?

Ошибка ConcurrentModificationException возникает в Java, когда коллекция модифицируется во время итерации по ней.

Причины возникновения

  • Модификация коллекции во время итерации
  • Использование непотокобезопасных коллекций в многопоточной среде
  • Неправильное использование итераторов
  • Одновременный доступ к коллекции из разных потоков

Как отладить ошибку

  1. Проверь модификацию коллекции - ищи места изменения во время итерации
  2. Проверь многопоточность - убедись в безопасности доступа
  3. Проверь использование итераторов - используй iterator.remove()
  4. Добавь синхронизацию - для многопоточного доступа

Как исправить ошибку

1. Используй iterator.remove() для безопасного удаления

 1// Неправильно
 2List<String> list = new ArrayList<>();
 3list.add("item1");
 4list.add("item2");
 5
 6for (String item : list) {
 7    if (item.equals("item1")) {
 8        list.remove(item); // ConcurrentModificationException
 9    }
10}
11
12// Правильно
13Iterator<String> iterator = list.iterator();
14while (iterator.hasNext()) {
15    String item = iterator.next();
16    if (item.equals("item1")) {
17        iterator.remove(); // безопасное удаление
18    }
19}

2. Используй потокобезопасные коллекции

1// Для многопоточного доступа
2import java.util.concurrent.*;
3
4// Потокобезопасные коллекции
5List<String> safeList = Collections.synchronizedList(new ArrayList<>());
6Map<String, String> safeMap = new ConcurrentHashMap<>();
7Queue<String> safeQueue = new ConcurrentLinkedQueue<>();

3. Создай копию коллекции для итерации

 1List<String> originalList = new ArrayList<>();
 2// заполнение списка
 3
 4// Создаем копию для безопасной итерации
 5List<String> copyList = new ArrayList<>(originalList);
 6for (String item : copyList) {
 7    if (someCondition) {
 8        originalList.remove(item); // безопасно, так как итерируемся по копии
 9    }
10}

4. Используй синхронизацию

 1private final List<String> list = new ArrayList<>();
 2private final Object lock = new Object();
 3
 4public void safeModification() {
 5    synchronized (lock) {
 6        for (String item : list) {
 7            if (someCondition) {
 8                list.remove(item);
 9            }
10        }
11    }
12}

Как мониторить подобные ошибки

  • Настрой логирование ConcurrentModificationException
  • Используй try-catch для обработки исключений
  • Настрой мониторинг с Prometheus и Grafana
  • Используй health checks для обнаружения проблем

FAQ

В: Когда возникает эта ошибка?

О: Ошибка возникает при разработке и выполнении, когда коллекция модифицируется во время итерации.

В: Как предотвратить эту ошибку?

О: Следуй best practices и используй потокобезопасные коллекции с правильной синхронизацией.

В: Какие инструменты помогают диагностировать ошибку?

О: Используй отладочные инструменты, логи и системы мониторинга.

Лучшие практики

  • Используй iterator.remove() для безопасного удаления
  • Применяй потокобезопасные коллекции в многопоточной среде
  • Создавай копии коллекций для безопасной итерации
  • Используй синхронизацию при необходимости
  • Пиши unit-тесты для проверки многопоточности