Skip to content

10 Что такое fail-fast и fail-safe итераторы? Как получить ConcurrentModification Exception в однопоточном приложении?

Fail-fast и fail-safe — это два подхода к обработке итераторов в Java, которые определяют, как итераторы реагируют на изменения коллекции во время итерации.

Fail-fast итераторы

  • Описание: Итераторы, которые работают в режиме fail-fast, проверяют состояние коллекции на предмет изменений (например, добавления или удаления элементов) во время итерации. Если коллекция была изменена после создания итератора, итератор выбрасывает исключение ConcurrentModificationException.
  • Примеры: Итераторы, предоставляемые стандартными коллекциями Java, такими как ArrayList, HashMap, и т.д., являются fail-fast итераторами.

Пример получения ConcurrentModificationException в однопоточном приложении:

import java.util.ArrayList;
import java.util.List;

public class FailFastExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        // Создаем итератор
        for (String item : list) {
            System.out.println(item);
            // Изменяем коллекцию во время итерации
            list.remove(item); // Это вызовет ConcurrentModificationException
        }
    }
}

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

Fail-safe итераторы

  • Описание: Итераторы, которые работают в режиме fail-safe, создают копию коллекции или используют другую структуру данных для итерации. Это позволяет избежать исключений, даже если коллекция изменяется во время итерации. Однако изменения, сделанные в оригинальной коллекции, не будут отражены в итераторе.
  • Примеры: Итераторы, предоставляемые классами, такими как CopyOnWriteArrayList и ConcurrentHashMap, являются fail-safe итераторами.

Пример использования fail-safe итератора:

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class FailSafeExample {
    public static void main(String[] args) {
        List<String> list = new CopyOnWriteArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        // Создаем итератор
        for (String item : list) {
            System.out.println(item);
            // Изменяем коллекцию во время итерации
            list.remove(item); // Это не вызовет ConcurrentModificationException
        }
    }
}

В этом примере, даже если мы удаляем элементы из CopyOnWriteArrayList во время итерации, исключение не будет выброшено, так как итератор работает с копией коллекции.

Заключение

  • Fail-fast итераторы: Быстро реагируют на изменения коллекции и выбрасывают ConcurrentModificationException, что помогает выявить ошибки в коде.
  • Fail-safe итераторы: Позволяют безопасно изменять коллекцию во время итерации, но изменения не будут отражены в итераторе.

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