Sincronización de ArrayList en Java

La implementación de ArrayList no está sincronizada de forma predeterminada. Significa que si un subproceso lo modifica estructuralmente y varios subprocesos acceden a él al mismo tiempo, debe sincronizarse externamente. La modificación estructural implica la adición o eliminación de elementos de la lista o redimensiona explícitamente la array de respaldo. Cambiar el valor de un elemento existente no es una modificación estructural.

Hay dos formas de crear una ArrayList sincronizada. 

1. Método Collections.synchronizedList(). 
2. Uso de CopyOnWriteArrayList.

Método 1: Usar el método Collections.synchronizedList()

Para realizar un acceso en serie, todo acceso a la lista de respaldo debe realizarse a través de la lista devuelta. Es imperativo que el usuario sincronice manualmente en la lista devuelta al iterar sobre ella. 

public static  List<T> synchronizedList(List<T> list)
  • Acepta una Lista que podría ser la implementación de la interfaz Lista . por ejemplo, ArrayList, LinkedList.
  • Devuelve una lista sincronizada (segura para subprocesos) respaldada por la lista especificada.
  • La lista de parámetros es la lista que se envolverá en una lista sincronizada.
  • T representa genérico

Java

// Java program to demonstrate working of
// 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)
        {
            // must be in synchronized block
            Iterator it = list.iterator();
 
            while (it.hasNext())
                System.out.println(it.next());
        }
    }
}
Producción

practice
code
quiz

Método 2: Uso de CopyOnWriteArrayList

CopyOnWriteArrayList<T> threadSafeList = new CopyOnWriteArrayList<T>();
  • Crea una lista vacía.
  • Implementa la interfaz de lista .
  • Es una variante segura para subprocesos de ArrayList.
  • T representa genérico

Una variante segura para subprocesos de ArrayList en la que todas las operaciones mutativas (por ejemplo, agregar, establecer, eliminar…) se implementan mediante la creación de una copia separada de una array subyacente . Logra seguridad de subprocesos mediante la creación de una copia separada de la Lista que es diferente del vector u otras colecciones utilizadas para proporcionar seguridad de subprocesos. 

  • Es útil cuando no puede o no quiere sincronizar el recorrido pero necesita evitar la interferencia entre subprocesos concurrentes.
  • Es costoso ya que implica una copia separada de la array con cada operación de escritura (por ejemplo, agregar, configurar, eliminar).
  • Es muy eficiente cuando tiene List y necesita recorrer sus elementos y no modificarlo con frecuencia.

El iterador no lanza ConcurrentModificationException incluso si se modifica copyOnWriteArrayList una vez que se crea el iterador. El iterador está iterando sobre la copia separada de ArrayList mientras se realiza una operación de escritura en otra copia de ArrayList.

Java

// Java program to illustrate the thread-safe ArrayList.
 
import java.io.*;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
 
class GFG
{
    public static void main (String[] args)
    {
        // creating a thread-safe Arraylist.
        CopyOnWriteArrayList<String> threadSafeList
            = new CopyOnWriteArrayList<String>();
 
        // Adding elements to synchronized ArrayList
        threadSafeList.add("geek");
        threadSafeList.add("code");
        threadSafeList.add("practice");
 
        System.out.println("Elements of synchronized ArrayList :");
 
        // Iterating on the synchronized ArrayList using iterator.
        Iterator<String> it = threadSafeList.iterator();
 
        while (it.hasNext())
            System.out.println(it.next());
    }
}
Producción

Elements of synchronized ArrayList :
geek
code
practice

¿Qué sucede si tratamos de modificar CopyOnWriteArrayList a través del método del iterador? 

Lanza UnsupportedOperationException si intenta modificar CopyOnWriteArrayList a través del propio método del iterador (por ejemplo, add(), set(), remove()). 

Java

// Java program to illustrate the thread-safe ArrayList
 
import java.io.*;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
 
class GFG
{
    public static void main (String[] args)
    {
        // creating a thread-safe Arraylist.
        CopyOnWriteArrayList<String> threadSafeList =
            new CopyOnWriteArrayList<String>();
 
        // Adding elements to synchronized ArrayList
        threadSafeList.add("geek");
        threadSafeList.add("code");
        threadSafeList.add("practice");
 
        System.out.println("Elements of synchronized ArrayList :");
 
        // Iterating on the synchronized ArrayList using iterator.
        Iterator<String> it = threadSafeList.iterator();
 
        while (it.hasNext())
        {
            String str = it.next();
            it.remove();
        }
    }
}

Error de tiempo de ejecución: 

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

Otros constructores de CopyOnWriteArrayList 

1. CopyOnWriteArrayList(Collection<? extends E> c) : crea una lista que contiene los elementos de la colección especificada, en el orden en que son devueltos por el iterador de la colección. 

2. CopyOnWriteArrayList(E[] toCopyIn) : crea una lista que contiene una copia de la array dada.

¿Por qué usar ArrayList cuando el vector está sincronizado?

  1. Rendimiento: Vector está sincronizado y es seguro para subprocesos, por lo que es un poco más lento que ArrayList.
  2. Funcionalidad: Vector se sincroniza a nivel de cada operación individual. Generalmente, a un programador le gusta sincronizar una secuencia completa de operaciones. La sincronización de operaciones individuales es menos segura y más lenta.
  3. Vectores obsoletos: los vectores se consideran obsoletos y no oficiales en desuso en java. Además, el vector se sincroniza en cada operación individual, lo que casi nunca se hace. La mayoría de los programadores de Java prefieren usar ArrayList ya que probablemente sincronizarán arrayList explícitamente de todos modos si necesitan sincronizar.

Debe leer: Vector vs ArrayList en Java

Este artículo es una contribución de Nitsdheerendra . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *