fail-fast
На самом деле это метод проектирования системы, как объясняется в Википедии:
При проектировании системы отказоустойчивая система может быстро сообщать о любых потенциальных сбоях в системе через определенные интерфейсы. Отказоустойчивая система не пытается продолжить работу системы при обнаружении сбоя, а немедленно останавливает текущие операции. Во время операции состояние системы проверяется на нескольких контрольных точках, что позволяет своевременно обнаруживать сбои. Ответственность отказоустойчивого модуля состоит в том, чтобы проверить, есть ли неисправность, и уведомить вышестоящую систему, чтобы она обработала неисправность как можно скорее после ее обнаружения.
Приведенный выше текст выглядит немного неясным, но на самом деле он означает, что отказоустойчивость — это механизм быстрого обнаружения системных сбоев. система обрабатывает эти сбои.
Противоположностью отказоустойчивости является отказоустойчивость. Как следует из названия, отказоустойчивость поддерживает работу системы после сбоя. Java использует оба механизма в контейнерах.
При использовании итератора для обхода контейнера итератор делится на два случая: один — отказоустойчивый, а другой — отказоустойчивый.
При отказоустойчивом обходе, если элементы контейнера будут изменены, будет сообщено ConcurrentModificationException, после чего обход будет прекращен.
отказоустойчивость означает, что при обходе элементов, даже если элементы контейнера модифицируются, исключение не будет выброшено, и обход не будет остановлен.
Эта статья основана на JDK1.8.
безотказная бетонная реализация
См. следующий код:
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
Iterator<Integer> itr = integers.iterator();
while (itr.hasNext()) {
Integer a = itr.next();
integers.remove(a);
}
Приведенный выше код, использующий ArrayList, сообщит об исключении ConcurrentModificationException.
List<Integer> integers = new CopyOnWriteArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
Iterator<Integer> itr = integers.iterator();
while (itr.hasNext()) {
Integer a = itr.next();
integers.remove(a);
}
Код, использующий CopyOnWriteArrayList, не сообщит об исключении.
Механизм отказоустойчивости связан с переменной modCount, которая записывает количество модификаций контейнера, что можно понимать как номер версии объекта-контейнера.
Так как же контейнер считается измененным?
- когда элемент контейнера удален
- Когда контейнер добавляет элемент
- Когда элементы в контейнере отсортированы
- Когда контейнер заменяется другим объектом-контейнером
Следует отметить, что модификация содержимого элемента в контейнере modCount не увеличится.
Когда контейнер использует итератор для перебора элементов, он присваивает modCount ожидаемому значению ModCount.
int expectedModCount = modCount;
В процессе итерации он будет постоянно проверять, равны ли значения ожидаемыхModCount и modCount.Если они не равны, то это означает, что другие операции модифицировали контейнер во время итерации контейнера, в результате чего значение modCount увеличится, то будет выдан отчет Исключение ConcurrentModificationException.
Примечание. Механизм отказоустойчивости используется не только в итераторах, но и в таких операциях, как добавление, удаление, изменение, запрос и сериализация контейнеров.
Есть ли способ удалить определенные элементы во время итерации? Просто используйте метод удаления самого итератора, который не вызовет исключения:
Iterator<Integer> itr = integers.iterator();
while (itr.hasNext()) {
if (itr.next() == 2) {
itr.remove();
}
}
Причина отсутствия исключений заключается в том, что после удаления элемента последнее значение modCount присваивается ожидаемомуModCount, код выглядит следующим образом:
// ListItr.remove() method
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
Отказоустойчивый механизм можно использовать для определения того, были ли изменены элементы контейнера, но следует отметить, что отказоустойчивый механизм не может гарантировать, что элементы контейнера не будут изменены.СинхронизироватьВ случае одновременной модификации элементов в контейнере. Первоначальной обязанностью механизма fast-fast было обнаружение системных ошибок, поэтому он используется только для обнаружения ошибок, а не для других целей.
Примечание: Синхронизация — это термин в параллельном программировании.Если фрагмент кода синхронизирован, это означает потокобезопасность.
воплощенные неудачные безопасные
В отличие от отказоустойчивого, отказоустойчивый контейнер может произвольно изменять элементы контейнера в процессе итерации, не сообщая об ошибке. Суть в том, что итерируется именно копия элемента-контейнера, то есть проходится копия элемента-контейнера, так что даже если исходный контейнер модифицируется, это не повлияет на проходимый в данный момент элемент.
CopyOnWriteArrayList — это контейнер, который поддерживает отказоустойчивость, а код для получения итератора выглядит следующим образом:
// CopyOnWriteArrayList.listIterator() method
Object[] es = getArray();
int len = es.length;
if (index < 0 || index > len)
throw new IndexOutOfBoundsException(outOfBounds(index, len));
return new COWIterator<E>(es, index);
// COWIterator inner class
private final Object[] snapshot;
private int cursor;
COWIterator(Object[] es, int initialCursor) {
cursor = initialCursor;
snapshot = es;
}
COWIterator делает снимок элементов контейнера, и последующие операции выполняются на этом снимке.
За поддержку отказоустойчивых функций взимается дополнительная плата:
- Элемент в итераторе не является последним состоянием контейнера
- Требует дополнительной памяти или дополнительных затрат времени
java.util
Контейнерный пакет имеет отказоустойчивый механизм,java.util.concurrent
Контейнеры под пакетом являются отказоустойчивыми.
REF:
- medium.com/@nobody.massagegreen…
- En. Wikipedia.org/wiki/fail-fat…
- Ну... Wikipedia.org/wiki/fail - это...
- JDK document
(над)
Статьи по Теме
- Серия контейнеров Java — обзор контейнеров Java
- Серия контейнеров Java — анализ исходного кода ArrayList
- Анализ исходного кода серии Java-контейнеров LinkedList
Обратите внимание на публичный аккаунт WeChat, пообщайтесь о других