Рубрики

Синхронизация ArrayList в Java

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

Существует два способа создания синхронизированного массива.
1. Метод Collections.synchronizedList ().
2. Использование CopyOnWriteArrayList.

Способ 1. Использование метода Collections.synchronizedList ()

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

public static  List<T> synchronizedList(List<T> list)
Accepts a List which could be implementation of List 
interface. e.g. ArrayList, LinkedList.
Returns a Synchronized(thread-safe) list backed by the 
specified list.
Parameter list is the list to be wrapped in a synchronize list.
T represents generic

// Java-программа для демонстрации работы
// Collections.synchronizedList

import java.util.*;

  

class GFG

{

    public static void main (String[] args)

    {

        List<String> list =

           Collections.synchronizedList(new ArrayList<String>());

  

        list.add("practice");

        list.add("code");

        list.add("quiz");

  

        synchronized(list)

        {

            // должен быть в синхронизированном блоке

            Iterator it = list.iterator();

  

            while (it.hasNext())

                System.out.println(it.next());

        }

    }

}

Выход:

practice
code
quiz

Способ 2: использование CopyOnWriteArrayList

  CopyOnWriteArrayList<T> threadSafeList = new CopyOnWriteArrayList<T>();
  
  Create an empty List.
  It implements List interface.
  It is a thread-safe variant of ArrayList.
  T represents generic

Потокобезопасный вариант ArrayList, в котором все мутативные операции (например, add, set, remove ..) реализованы путем создания отдельной копии базового массива . Он обеспечивает безопасность потоков , создавая отдельную копию List, которая отличается от использования векторов или других коллекций для обеспечения безопасности потоков .

  • Это полезно, когда вы не можете или не хотите синхронизировать обход, но должны предотвращать помехи между параллельными потоками.
  • Это дорого, так как включает в себя отдельную копию массива с каждой операцией записи (например, добавить, установить, удалить ..)
  • Это очень эффективно, когда у вас есть List, и вам нужно обходить его элементы и не часто его изменять.

Iterator не генерирует ConcurrentModificationException, даже если copyOnWriteArrayList изменяется после создания итератора, поскольку итератор выполняет итерацию по отдельной копии ArrayList, в то время как операция записи выполняется для другой копии ArrayList.

// Java-программа для иллюстрации многопоточного ArrayList.

import java.io.*;

import java.util.Iterator;

import java.util.concurrent.CopyOnWriteArrayList;

  

class GFG

{

    public static void main (String[] args)

    {

        // создаем потокобезопасный Arraylist.

        CopyOnWriteArrayList<String> threadSafeList

            = new CopyOnWriteArrayList<String>();

  

        // Добавление элементов в синхронизированный ArrayList

        threadSafeList.add("geek");

        threadSafeList.add("code");

        threadSafeList.add("practice");

  

        System.out.println("Elements of synchronized ArrayList :");

  

        // Итерация в синхронизированном ArrayList с использованием итератора.

        Iterator<String> it = threadSafeList.iterator();

  

        while (it.hasNext())

            System.out.println(it.next());

    }

}

Выход:

Elements of synchronized ArrayList :
geek
code
practice

Что произойдет, если мы попытаемся изменить CopyOnWriteArrayList через собственный метод итератора?
Он выдает UnsupportedOperationException, если вы пытаетесь изменить CopyOnWriteArrayList через собственный метод итератора (например, add (), set (), remove ()).

// Java-программа для иллюстрации многопоточного ArrayList

import java.io.*;

import java.util.Iterator;

import java.util.concurrent.CopyOnWriteArrayList;

  

class GFG

{

    public static void main (String[] args)

    {

        // создаем потокобезопасный Arraylist.

        CopyOnWriteArrayList<String> threadSafeList =

            new CopyOnWriteArrayList<String>();

  

        // Добавление элементов в синхронизированный ArrayList

        threadSafeList.add("geek");

        threadSafeList.add("code");

        threadSafeList.add("practice");

  

        System.out.println("Elements of synchronized ArrayList :");

  

        // Итерация в синхронизированном ArrayList с использованием итератора.

        Iterator<String> it = threadSafeList.iterator();

  

        while (it.hasNext())

        {

            String str = it.next();

            it.remove();

        }

    }

}

Ошибка выполнения:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove
        (CopyOnWriteArrayList.java:1176)
    at GFG.main(File.java:28)

Другие конструкторы CopyOnWriteArrayList:
1. CopyOnWriteArrayList (Collection <? Extends E> c) : создает список, содержащий элементы указанной коллекции, в том порядке, в котором они возвращаются итератором коллекции.
2. CopyOnWriteArrayList (E [] toCopyIn) : Создает список, содержащий копию данного массива.


Зачем использовать arrayList, когда вектор синхронизирован?

  1. Производительность: Vector синхронизирован и поточно-ориентирован, поэтому он немного медленнее, чем ArrayList.
  2. Функциональность: вектор синхронизируется на уровне каждой отдельной операции. Обычно программисту нравится синхронизировать всю последовательность операций. Синхронизация отдельных операций менее безопасна и медленнее.
  3. Векторы устарели: векторы считаются устаревшими и неофициально устарели в Java. Кроме того, вектор синхронизируется на каждой отдельной операции, которая почти никогда не выполняется. В основном Java-программисты предпочитают использовать ArrayList, так как они, вероятно, будут в любом случае явно синхронизировать arrayList, если им потребуется синхронизация.

Связанная статья: Vector против ArrayList в Java

Ссылки:

Эта статья предоставлена Nitsdheerendra . Если вам нравится GeeksforGeeks и вы хотели бы внести свой вклад,
Вы также можете написать статью с помощью contrib.geeksforgeeks.org или отправить свою статью по адресу contrib@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Синхронизация ArrayList в Java

0.00 (0%) 0 votes