Рубрики
Без рубрики

CopyOnWriteArrayList на Java

CopyOnWriteArrayList в примере Java. CopyOnWriteArrayList-это класс параллельной коллекции, чтобы избежать исключения ConcurrentModificationException, java.util.concurrent

Автор оригинала: Pankaj Kumar.

CopyOnWriteArrayList в Java-это потокобезопасная реализация интерфейса списка. CopyOnWriteArrayList был добавлен в Java 1.5 и является частью платформы коллекций.

Исключение Java ArrayList и ConcurrentModificationException

ArrayList является одной из основных реализаций интерфейса списка и является частью Java Collections Framework . Мы можем использовать итератор для обхода элементов списка массивов.

Давайте проверим пример программы ArrayList.

Давайте проверим пример программы ArrayList.

package com.journaldev.collections;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class ConcurrentListExample {

    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        
        // get the iterator
        Iterator it = list.iterator();
        
        //manipulate list while iterating
        while(it.hasNext()){
            System.out.println("list is:"+list);
            String str = it.next();
            System.out.println(str);
            if(str.equals("2"))list.remove("5");
            if(str.equals("3"))list.add("3 found");
            //below code don't throw ConcurrentModificationException
            //because it doesn't change modCount variable of list
            if(str.equals("4")) list.set(1, "4");
        }
    }

}

Когда мы запускаем вышеуказанную программу, мы получаем java.util.ConcurrentModificationException как только список массивов будет изменен.

Это происходит потому, что итератор ArrayList быстродействующий по дизайну. Это означает, что после создания итератора, если список массивов изменен, он создает исключение ConcurrentModificationException .

Если вы проверите журнал консоли, вы заметите, что исключение создается методом итератора next () . Если вы посмотрите в исходный код ArrayList, следующий метод вызывается каждый раз, когда мы вызываем next() на итераторе, который создает исключение.

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

Здесь modCount – это переменная ArrayList, которая содержит количество изменений, и каждый раз, когда мы используем метод add , remove или trimToSize , она увеличивается. expectedModCount – это переменная итератора, которая инициализируется при создании итератора с тем же значением, что и modCount . Это объясняет, почему мы не получаем исключения, если используем метод set для замены любого существующего элемента.

Таким образом, в основном итератор выдает ConcurrentModificationException , если размер списка изменен.

CopyOnWriteArrayList на Java

Иногда мы хотим добавить или удалить элементы из списка, если мы найдем какой – то конкретный элемент, в этом случае мы должны использовать класс параллельной коллекции – CopyOnWriteArrayList . Это потокобезопасный вариант java.util.Список массивов, в котором все мутационные операции (добавление, установка и т. Д.) Реализуются путем создания новой копии базового массива.

CopyOnWriteArrayList вносит дополнительную перегрузку в обработку, но это очень эффективно, когда количество изменений минимально по сравнению с количеством операций обхода.

Если мы изменим реализацию на CopyOnWriteArrayList , то мы не получим никаких исключений, и ниже приведен результат.

list is:[1, 2, 3, 4, 5]
1
list is:[1, 2, 3, 4, 5]
2
list is:[1, 2, 3, 4]
3
list is:[1, 2, 3, 4, 3 found]
4
list is:[1, 4, 3, 4, 3 found]
5

Обратите внимание, что это позволяет изменять список, но не изменяет итератор, и мы получаем те же элементы, что и в исходном списке.