Отказоустойчивый итератор против отказоустойчивого итератора

Отказоустойчивый итератор против отказоустойчивого итератора

1. Вступление

В этой статье мы познакомим вас с концепцией Fail-Fast и Fail-SafeIterators.

Системы Fail-Fast прерывают работу настолько быстро, насколько это возможно, немедленно обнаруживая сбои и останавливая всю операцию.

Тогда какFail-Safe systems don’t abort an operation in the case of a failure. Such systems try to avoid raising failures as much as possible.

2. Fail-FastIterators

Отказоустойчивые итераторы в Java не действуют при изменении базовой коллекции.

Collections поддерживает внутренний счетчикmodCount. Каждый раз, когда элемент добавляется или удаляется изCollection, этот счетчик увеличивается.

При итерации при каждом вызовеnext() текущее значениеmodCount сравнивается с начальным значением. Если есть несоответствие, он выдаетConcurrentModificationException, что прерывает всю операцию.

Итераторы по умолчанию дляCollections изjava.util package, такие какArrayList,HashMap и т. Д. работают без сбоев.

ArrayList numbers = // ...

Iterator iterator = numbers.iterator();
while (iterator.hasNext()) {
    Integer number = iterator.next();
    numbers.add(50);
}

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

Поведение Fail-Fast не гарантируется во всех сценариях, так как невозможно предсказать поведение в случае одновременных модификаций. These iterators throw ConcurrentModificationException on a best effort basis.

Если при итерацииCollection,an item is removed using Iterator‘s remove() method, that’s entirely safe and doesn’t throw an exception.

Однако, если для удаления элемента используется методCollection‘sremove(), он генерирует исключение:

ArrayList numbers = // ...

Iterator iterator = numbers.iterator();
while (iterator.hasNext()) {
    if (iterator.next() == 30) {
        iterator.remove(); // ok!
    }
}

iterator = numbers.iterator();
while (iterator.hasNext()) {
    if (iterator.next() == 40) {
        numbers.remove(2); // exception
    }
}

3. Отказоустойчивые итераторы

Отказоустойчивые итераторы предпочитают отсутствие сбоев за неудобства обработки исключений.

Эти итераторы создают клон фактическогоCollection и перебирают его. Если после создания итератора происходит какое-либо изменение, копия все равно остается нетронутой. Следовательно, этиIterators продолжают цикл поCollection, даже если он был изменен.

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

Это означает, чтоif aCollection is modified while being iterated over, what the Iterator sees is weakly guaranteed. Это поведение может отличаться для разныхCollections и задокументировано в документации Javadocs каждого такогоCollection.

Однако отказоустойчивыеIteratorsимеют несколько недостатков. Одним из недостатков является то, чтоIterator isn’t guaranteed to return updated data from the Collection, поскольку он работает с клоном, а не с фактическимCollection.

Другой недостаток - накладные расходы на создание копииCollection, как в отношении времени, так и памяти.

Iterators вCollections из пакетаjava.util.concurrent, напримерConcurrentHashMap,CopyOnWriteArrayList и т. д. являются отказоустойчивыми по своей природе.

ConcurrentHashMap map = new ConcurrentHashMap<>();

map.put("First", 10);
map.put("Second", 20);
map.put("Third", 30);
map.put("Fourth", 40);

Iterator iterator = map.keySet().iterator();

while (iterator.hasNext()) {
    String key = iterator.next();
    map.put("Fifth", 50);
}

В приведенном выше фрагменте кода мы используем Fail-SafeIterator. Следовательно, даже несмотря на то, что новый элемент добавляется кCollection во время итерации, он не вызывает исключения.

Итератор по умолчанию_ for the _ConcurrentHashMap слабо согласован. Это означает, что этотIterator может допускать параллельную модификацию, пересекает элементы в том виде, в каком они существовали, когда был построенIterator, и может (но не гарантированно) отражать изменения вCollection после построения Iterator.

Следовательно, в приведенном выше фрагменте кода итерация повторяется пять раз, что означаетit does detect the newly added element to the Collection.

4. Заключение

В этом руководстве мы увидели, что означают Fail-Safe и Fail-FastIterators и как они реализованы в Java.

Полный код, представленный в этой статье, доступенover on GitHub.