В Java есть два типа итераторов: отказоустойчивые и отказоустойчивые.
Что это значит, и чем они отличаются?
В Java есть два типа итераторов: отказоустойчивые и отказоустойчивые.
Что это значит, и чем они отличаются?
Ответы:
В чем разница между ними ...
«Отказоустойчивый» ( в инженерии ) означает, что что-то выходит из строя так, что не причиняет никакого ущерба или причиняет им минимальный ущерб. Строго говоря, в Java нет такого понятия, как отказоустойчивый итератор. Если итератор выходит из строя (в обычном смысле слова «сбой»), вы можете ожидать повреждения.
Я подозреваю, что вы на самом деле имеете в виду «слабо согласованные» итераторы. В javadoc говорится:
«Большинство реализаций параллельных коллекций (включая большинство очередей) также отличаются от обычных соглашений java.util тем, что их итераторы и сплитераторы обеспечивают слабо согласованный, а не быстрый обход».
Как правило, слабая согласованность означает, что если коллекция изменяется одновременно с итерацией, гарантии того, что видит итерация, слабее. (Подробности будут указаны в документации javadocs для каждого параллельного набора классов.)
«Безотказный» ( в проектировании систем ) означает, что условие отказа тщательно проверяется, так что условие отказа (где возможно 1 ) обнаруживается до того, как может быть нанесен слишком большой ущерб. В Java отказоустойчивый итератор дает сбой, создавая ConcurrentModificationException
.
Альтернатива «отказоустойчивому» и «слабо согласованному» является семантическим, когда итерация терпит неудачу непредсказуемо; например, иногда давать неправильный ответ или генерировать неожиданное исключение. (Это было поведение некоторых стандартных реализаций Enumeration
API в ранних версиях Java.)
... и отличаются ли они от итератора, который мы используем для сбора.
Нет. Это свойства итераторов, реализованные стандартными типами Collection; т.е. они либо «быстро выходят из строя», либо «слабо согласованы» ... при правильном использовании в отношении синхронизации и модели памяти Java 1 .
Отказоустойчивые итераторы обычно реализуются с использованием volatile
счетчика в объекте коллекции.
Iterator
создается, текущее значение счетчика внедряется в Iterator
объект.Iterator
операция выполняется, метод сравнивает два значения счетчика и выдает CME, если они различны.Напротив, слабо согласованные итераторы обычно легковесны и используют свойства внутренних структур данных каждой параллельной коллекции. Общей закономерности нет. Если вам интересно, прочтите исходный код для разных классов коллекций.
1 - Наездник заключается в том, что безотказное поведение предполагает, что идентификатор приложения правильный в отношении синхронизации и модели памяти. Это означает, что (например), если вы выполняете итерацию ArrayList
без надлежащей синхронизации, результатом может быть поврежденный результат списка. Механизм «быстрого сбоя», вероятно, обнаружит одновременную модификацию (хотя это не гарантируется), но не обнаружит лежащее в основе повреждение. Например, в javadoc for Vector.iterator()
сказано следующее:
«Безотказное поведение итератора не может быть гарантировано, поскольку, вообще говоря, невозможно дать какие-либо жесткие гарантии при наличии несинхронизированной одновременной модификации. Отказоустойчивые итераторы выбирают из соображений
ConcurrentModificationException
максимального усилия. Следовательно, это было бы неправильно писать программу, правильность которой зависит от этого исключения: безотказное поведение итераторов следует использовать только для обнаружения ошибок ».
setArray
любые изменения.
Это довольно отказоустойчивые и слабосогласованные типы:
Итераторы из java.util
пакета бросают, ConcurrentModificationException
если коллекция была изменена методами коллекции (добавление / удаление) во время итерации
Итераторы из java.util.concurrent
пакета обычно выполняют итерацию по снимку и допускают одновременные изменения, но могут не отражать обновления коллекции после создания итератора.
Iterator
или не Enumeration
указывайте поведение как отказоустойчивое или отказоустойчивое. Это конкретные реализации (т.е. определенные методы коллекции iterator()
/ и elements()
т.д., которые возвращают эти объекты), которые определяют поведение. 2) Типичные реализации перечисления не являются ни отказоустойчивыми, ни отказоустойчивыми .
Единственная разница в том, что отказоустойчивый итератор не генерирует никаких исключений, в отличие от отказоустойчивого итератора.
Если Collection модифицируется структурно, пока один поток выполняет итерацию по нему. Это связано с тем, что они работают с клоном Collection вместо исходной коллекции, и поэтому они называются отказоустойчивым итератором.
Итератор CopyOnWriteArrayList является примером отказоустойчивого итератора. Итератор, написанный ConcurrentHashMap keySet, также является отказоустойчивым итератором и никогда не генерирует исключение ConcurrentModificationException в Java.
Этот сценарий связан с «параллельной обработкой», что означает, что к одному и тому же ресурсу обращаются более одного пользователя. В такой ситуации один из пользователей пытается изменить этот ресурс, что вызывает исключение ConcurrentProcessingException, потому что в этом случае другой пользователь получает неправильные данные. Оба эти типа относятся к подобным ситуациям.
Проще говоря,
Быстрый отказ:
Отказоустойчивый: