Java-класс CopyOnWriteArrayList

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 в следующих случаях:

  1. Когда список будет использоваться в параллельной среде.
  2. Число итераций превышает число операций мутации.
  3. Итераторы должны иметь моментальную версию списка на момент их создания.
  4. Мы не хотим синхронизировать доступ к потокам программно.

 

7. Производительность Java CopyOnWriteArrayList

Из-за дополнительного шага создания нового резервного массива каждый раз при обновлении списка производительность хуже, чем у ArrayList.
Операции чтения не приводят к снижению производительности, и оба класса выполняют их одинаково.

 

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

В этом уроке по Java Collection мы научились использовать класс CopyOnWriteArrayList, его конструкторы, методы и варианты использования. Мы изучили внутреннюю работу CopyOnWriteArrayList в java, а также CopyOnWriteArrayList против синхронизированного arraylist.

Мы рассмотрели пример программы Java CopyOnWriteArrayList, чтобы продемонстрировать, как работают итераторы снимков.

Пишите мне свои вопросы в комментариях.

Ссылка:

CopyOnWriteArrayList Документация Java

Прокрутить вверх