Por favor, activa JavaScript y desactiva tu adblock para este sitio

El Javatar

Blog dedicado a la Programación en Java, C, PHP, Phyton, HTML, SQL y Mucho Más

lunes, 27 de noviembre de 2017

¿Qué es un CopyOnWriteArrayList en Java?

Qué es un CopyOnWriteArrayList en Java

CopyOnWriteArrayList es una clase para trabajar colecciones concurrentes presentada en el API de concurrencia de Java a partir de la versión 5 junto con la otra muy popular clase ConcurrentHashMap. CopyOnWriteArrayList implementa la interface List, tal como lo hacen las clases ArrayList, Vector y LinkedList, con la diferencia de que CopyOnWriteArrayList es una colección thread-safety y logra la seguridad de subprocesos de una manera ligeramente diferente que la clase Vector u otra clase de colecciones thread-safe.

Como su nombre lo indica, CopyOnWriteArrayList crea una copia del ArrayList subyacente con cada operación de escritura, por ejemplo, agregar, eliminar o cuando se modifican valores. Es por esta razón que CopyOnWriteArrayList solo es adecuado cuando trabajemos con una lista que se lea con frecuencia pero se modifique raramente.


Normalmente,  CopyOnWriteArrayList puede llegar a ser ineficiente porque implica costosas copias del Array con cada operación de escritura, pero es muy eficiente si lo que necesitamos es una lista donde las iteraciones superan las mutaciones, es decir, cuando las operaciones de escritura se dan con poca frecuencia.

El iterador de CopyOnWriteArrayList es fail-safe (a prueba de fallas) y no lanza excepciones de tipo ConcurrentModificationException, incluso si la lista se modifica una vez que comienza la iteración, ya que el Iterador actúa sobre una copia separada del ArrayList. En consecuencia, todas las actualizaciones realizadas fuera de un CopyOnWriteArrayList no están disponibles para su Iterator, es decir, que no podremos ver los cambios que realice otro hilo sobre la colección de datos.

Así pues, en este tutorial de Java Collections no sólo veremos qué es un CopyOnWriteArrayList, también expondré la diferencia entre ArrayList y CopyOnWriteArrayList y un ejemplo sencillo de un programa Java con el que aprenderemos cómo usar un CopyOnWriteArrayList en Java.

Diferencia entre CopyOnWriteArrayList y ArrayList en Java

Ya hemos visto lo que es un CopyOnWriteArrayList en Java y cómo éste logra la seguridad del thread al crear una copia separada de la colección para cada operación de escritura.

Ahora veamos algunas diferencias entre ArrayList y CopyOnWriteArrayList en Java, las cuales son ambas implementaciones de la interface List:

1) La principal diferencia entre CopyOnWriteArrayList y ArrayList en Java es que CopyOnWriteArrayList es una colección segura para subprocesos (thread-safe), mientras que ArrayList no es seguro para subprocesos y no puede ser usado en un entorno de múltiples hilos.

2) La segunda diferencia entre ArrayList y CopyOnWriteArrayList es que el Iterador de un  ArrayList es fail-fast y lanzará una excepción de tipo ConcurrentModificationException una vez que detecta cualquier modificación en la Lista mientras está iterando; por el contrario, el Iterador de un CopyOnWriteArrayList es fail-safe y no lanza excepciones de tipo ConcurrentModificationException.

3) La tercera diferencia entre CopyOnWriteArrayList y ArrayList es que el iterador del primero no soporta la operación para eliminar elementos, mientras que el iterador del segundo si soporta el método remove().

Ejemplo de CopyOnWriteArrayList en Java

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

/**
 *
 * Programa para demostrar como usar CopyOnWriteArrayList en Java,
 * y como usar el Iterador de CopyOnWriteArrayList
 *
 * @author Andrés M. Barragán (eljavatar)
 */
public class EjemploCopyOnWriteArrayList {

    public static void main(String args[]) {
     
        CopyOnWriteArrayList<String> listThreadSafe = new CopyOnWriteArrayList<>();
        listThreadSafe.add("Asia");
        listThreadSafe.add("Africa");
        listThreadSafe.add("America");
        listThreadSafe.add("Europa");
        listThreadSafe.add("Oceania");
     
        // Las operaciones add y remove no están soportadas por el Iterador de CopyOnWriteArrayList
        Iterator<String> failSafeIterator = listThreadSafe.iterator();
        while (failSafeIterator.hasNext()) {
            System.out.printf("Lectura del CopyOnWriteArrayList : %s %n", failSafeIterator.next());
            failSafeIterator.remove(); // Esta línea lanzará una excepción. (Comentar para ejecutar completo)
        }
    }
}

La salida de este código (comentando la línea donde se usa el método remove()) sería la siguiente:

Lectura del CopyOnWriteArrayList : Asia 
Lectura del CopyOnWriteArrayList : Africa 
Lectura del CopyOnWriteArrayList : America 
Lectura del CopyOnWriteArrayList : Europa 
Lectura del CopyOnWriteArrayList : Oceania 

Si lo ejecutamos sin comentar la línea donde se usa el método remove(), el resultado será el siguiente:

Lectura del CopyOnWriteArrayList : Asia 

Exception in thread "main" java.lang.UnsupportedOperationException
 at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1176)
 at EjemploCopyOnWriteArrayList.main(EjemploCopyOnWriteArrayList.java:26)
Command exited with non-zero status 1

Esto es todo acerca de lo que es un CopyOnWriteArrayList en Java y su diferencia respecto a un ArrayList. En resumen, podemos concluir que deberíamos usar CopyOnWriteArrayList si nuestro objetivo es principalmente iterar sobre la lista sin modificarla.

No hay comentarios.:

Publicar un comentario