Java CopyOnWriteArrayList — это потокобезопасный вариант ArrayList, в котором все мутационные операции(сложение, установка и т. д.) реализуются путем создания новой копии базового массива.
Его неизменяемый метод итератора в стиле моментального снимка использует ссылку на состояние массива в точке создания итератора. Это помогает в случаях, когда операции обхода значительно превосходят по количеству операции обновления списка, и мы не хотим синхронизировать обходы и при этом хотим потокобезопасности при обновлении списка.
1. Иерархия CopyOnWriteArrayList
Класс CopyOnWriteArrayList реализует следующие интерфейсы – List, RandomAccess, Cloneable иSerializable.
public class CopyOnWriteArrayList<E>implements List<E>,RandomAccess,Cloneable,Serializable{private transient volatile Object[] array;//implementation}
2. Возможности CopyOnWriteArrayList
Вот важные вещи, которые следует знать о классе Java CopyOnWriteArrayList:
- Класс CopyOnWriteArrayList реализует интерфейсы List и RandomAccess и, таким образом, предоставляет все функциональные возможности, доступные в классе ArrayList.
- Использование CopyOnWriteArrayList является затратным для операций обновления, поскольку каждая мутация создает клонированную копию базового массива и добавляет/обновляет в него элемент.
- Это потокобезопасная версия ArrayList. Каждый поток, обращающийся к списку, видит свою собственную версию снимка резервного массива, созданного при инициализации итератора для этого списка.
- Поскольку при создании итератора он получает снимок базового массива, он не выдает исключение ConcurrentModificationException.
- Операции мутации на итераторах(удаление, установка и добавление) не поддерживаются. Эти методы выдают исключение UnsupportedOperationException.
- CopyOnWriteArrayList — это параллельная замена синхронизированному списку, обеспечивающая лучшую параллелизм, когда число итераций превышает число мутаций.
- Он допускает дублирование элементов и неоднородные объекты(используйте дженерики для получения ошибок времени компиляции).
- Поскольку он создает новую копию массива каждый раз при создании итератора, производительность ниже, чем у ArrayList.
3. Пример CopyOnWriteArrayList
Программа Java, демонстрирующая, как итераторы, созданные в разное время, просматривают версию снимка списка в CopyOnWriteArrayList. В данном примере мы сначала создали список и itr1, когда список имел элементы(1,2,3).
Затем мы добавили еще один элемент в список и снова создали итератор itr2.
Наконец, мы проверили элементы в обоих итераторах.
CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>(new Integer[] {1,2,3});System.out.println(list); //[1, 2, 3]//Get iterator 1Iterator<Integer> itr1 = list.iterator();//Add one element and verify list is updatedlist.add(4);System.out.println(list); //[1, 2, 3, 4]//Get iterator 2Iterator<Integer> itr2 = list.iterator();System.out.println("====Verify Iterator 1 content====");itr1.forEachRemaining(System.out :: println); //1,2,3System.out.println("====Verify Iterator 2 content====");itr2.forEachRemaining(System.out :: println); //1,2,3,4
Вывод программы.
[1, 2, 3][1, 2, 3, 4]====Verify Iterator 1 content====123====Verify Iterator 2 content====1234
4. Конструкторы CopyOnWriteArrayList
- CopyOnWriteArrayList() : создает пустой список.
- CopyOnWriteArrayList(Collection c): создает список, содержащий элементы указанной коллекции в том порядке, в котором они возвращаются итератором коллекции.
- CopyOnWriteArrayList(object[] array) : создает список, содержащий копию указанного массива.
5. Методы CopyOnWriteArrayList
Класс CopyOnWriteArrayList все методы, которые поддерживаются в классе ArrayList. Поведение отличается только в случае итераторов(итератор моментального снимка) И нового резервного массива, созданного во время мутаций в списке.
Кроме того, он предоставляет несколько методов, которые являются дополнительными к этому классу.
- boolean addIfAbsent(object o) : добавить элемент, если его нет.
- int addAllAbsent(Collection c) : добавляет все элементы указанной коллекции, которые еще не содержатся в этом списке, в конец этого списка в том порядке, в котором они возвращаются итератором указанной коллекции.
Информацию обо всех других поддерживаемых методах см. в разделе Методы ArrayList.
6. Варианты использования Java CopyOnWriteArrayList
Мы можем предпочесть использование CopyOnWriteArrayList вместо обычного ArrayList в следующих случаях:
- Когда список будет использоваться в параллельной среде.
- Число итераций превышает число операций мутации.
- Итераторы должны иметь моментальную версию списка на момент их создания.
- Мы не хотим синхронизировать доступ к потокам программно.
7. Производительность Java CopyOnWriteArrayList
Из-за дополнительного шага создания нового резервного массива каждый раз при обновлении списка производительность хуже, чем у ArrayList.
Операции чтения не приводят к снижению производительности, и оба класса выполняют их одинаково.
8. Заключение
В этом уроке по Java Collection мы научились использовать класс CopyOnWriteArrayList, его конструкторы, методы и варианты использования. Мы изучили внутреннюю работу CopyOnWriteArrayList в java, а также CopyOnWriteArrayList против синхронизированного arraylist.
Мы рассмотрели пример программы Java CopyOnWriteArrayList, чтобы продемонстрировать, как работают итераторы снимков.
Пишите мне свои вопросы в комментариях.
Ссылка: