В однопоточной системе, в чем разница между ArrayList, Collections.getSynchronisedList () и CopyOnWriteArrayList? - PullRequest
0 голосов
/ 04 июля 2019

Итак, я понял, что у нас есть arrayList, который реализует интерфейс List интерфейса Collection.ArrayList не может быть повторен и изменен одновременно, и он не был синхронизирован, в игру вступила синхронизированная версия List.Теперь это обеспечивает один из способов достижения синхронизации потока, который выполняет итерацию по списку, должен завершиться, чтобы другой поток в том же экземпляре списка мог измениться.Проблема с синхронизированной версией заключалась в том, что локака была над завершенным экземпляром, поэтому она должна ждать завершения потока 1, чтобы другой поток мог изменить список.По этой причине появился CopyOnwriteArrayList, обеспечивающий одновременное чтение и изменение нескольких потоков.

Все это происходило в многопоточной системе.

Для однопоточной системы рассмотрите следующие коды

case1- ArrayList

/***************concurrent modification exception************************/


List l= new ArrayList<String>();
        l.add("A");
        l.add("b");
        l.add("c");
        l.add("d");

        Iterator itr= l.iterator();

        while(itr.hasNext()) {
            System.out.println(itr.next());
            l.add("e");
        }
        System.out.println(l.toString());

        /***************concurrent modification exception************************/

В вышеприведенном случае1 получить исключение concurrentModification для Arraylist

case-2 Collection.synchronisedList

/***************concurrent modification exception ON sync List************************/
        List l= new ArrayList<String>();
        l.add("A");
        l.add("b");
        l.add("c");
        l.add("d");


        List syncList= Collections.synchronizedList(l);     

        Iterator itr= syncList.iterator();
        while(itr.hasNext()) {
            System.out.println(itr.next());
            syncList.add("E");


        }
        System.out.println(syncList.toString());

        /***************concurrent modification exception ON sync List************************/

В указанном выше случае я все ещеполучить одновременную модификацию

case-3- CopyOnWriteArrayList

/***************NO concurrent modification exception ON COWL************************/
        List l= new ArrayList<String>();
        l.add("A");
        l.add("b");
        l.add("c");
        l.add("d");


        CopyOnWriteArrayList cowl= new CopyOnWriteArrayList<>(l);       

        Iterator itr= cowl.iterator();
        while(itr.hasNext()) {
            System.out.println(itr.next());
            cowl.add("e");
        }
        System.out.println(cowl.toString());
        System.out.println(l.toString());
        /***************NO concurrent modification exception ON COWL************************/

Вывод- [A, b, c, d, e, e, e, e] [A, b, c, d]

Теперь у меня есть 2 вопроса

Вопрос 1. Какая разница между тремя типами списков в однопоточной системе?

Вопрос2 - Капот обновляется, оригинальный список остается прежнимтогда как итерация и модификация происходят одновременно?

1 Ответ

0 голосов
/ 04 июля 2019

Вопрос 1: Разница между тремя реализациями списка

Различия между тремя списками одинаковы, независимо от того, является ли программа однопоточной или многопоточной. Если предположить, что вопрос больше о последствиях, то SynchronizedList и CopyOnWriteArrayList повлекут за собой ненужные потери производительности.

SynchronizedList: это оболочка для базового списка, поэтому все методы будут включать дополнительное делегирование в свернутый список.

CopyOnWriteArrayList: имеет дорогостоящие операции мутации, поскольку они включают в себя создание копии базового массива.

В дополнение к снижению производительности, как вы указали, CopyOnWriteArrayList позволяет вносить изменения в список, из которого был создан итератор (подробнее об этом ниже).

Вопрос 2. Как итерация и модификация происходят одновременно?

С CopyOnWriteArrayList они не являются. Это в основном идея этой структуры данных. Выполнение кода в вашем сообщении также выводит результат 4 вызовов на System.out.println, который печатает (по одному на строку): A b c d, показывая, таким образом, что, даже если вы добавляете элементы в список, эти добавления не отражаются в структура данных, поддерживающая итератор.

Дополнительное уточнение

Получение ConcurrentModificationException не обязательно указывает на проблему параллелизма (то есть многопоточности). То, что вы заметили, согласуется с документацией об исключении:

Обратите внимание, что это исключение не всегда указывает на то, что объект был одновременно изменен другим потоком. Если один поток выдает последовательность вызовов методов, которая нарушает контракт объекта, объект может вызвать это исключение. Например, если поток изменяет коллекцию напрямую, в то время как он выполняет итерацию по коллекции с помощью итератора с быстрой ошибкой, итератор сгенерирует это исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...