Listar la colección de clases de seguridad en JUC

Colección insegura

En aplicaciones de un solo subproceso, generalmente se adopta new ArrayList()para especificar una colección de Lista para almacenar datos repetibles.

Pero en el subproceso múltiple, a menudo ocurren problemas inesperados. El código es el siguiente:

import java.util.*;
public class ListTest {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        // 创建list集合
        //List<String> lists = Arrays.asList("1", "2", "3");
        // 不安全
        List<String> lists = new ArrayList<>();

        // 开启十个线程增加数据
        for (int i = 1; i <= 40; i++) {
    
    
            new Thread(()->{
    
    
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+lists);
            },String.valueOf(i)).start();
        }
    }
}

Los resultados de su operación son los siguientes:
Inserte la descripción de la imagen aquí
operación multiproceso del mismo conjunto de información de objeto, a menudo aparecerán java.util.ConcurrentModificationExceptionmensajes de error anormales.

Medidas de seguridad proporcionadas en Java

En el lenguaje Java, se proporcionan una nueva colección y java.util.Vectorclase List . Para obtener más información, consulte el siguiente código:

import java.util.*;
public class ListTest {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        // 创建list集合
        //List<String> lists = Arrays.asList("1", "2", "3");
        // 不安全
        //List<String> lists = new ArrayList<>();
		List<String> lists = new Vector<>();

        // 开启十个线程增加数据
        for (int i = 1; i <= 40; i++) {
    
    
            new Thread(()->{
    
    
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+lists);
            },String.valueOf(i)).start();
        }
    }
}

El registro de ejecución es el siguiente:
Inserte la descripción de la imagen aquí
no aparecerá ningún java.util.ConcurrentModificationExceptionmensaje de error.

¿Por qué se puede garantizar el funcionamiento seguro de los datos?
Inserte la descripción de la imagen aquí

Tomado synchronizedpara la implementación del método de bloqueo de llamadas, multiproceso para garantizar la seguridad de la operación de adición.

Colección de listas seguras bajo JUC

En el paquete JUC, hay varias formas de crear una colección segura.

  • 方式 一 : Collections.synchronizedList (new ArrayList <> ());
import java.util.*;
public class ListTest {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
		List<String> lists = Collections.synchronizedList(new ArrayList<>());

        // 开启十个线程增加数据
        for (int i = 1; i <= 40; i++) {
    
    
            new Thread(()->{
    
    
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+lists);
            },String.valueOf(i)).start();
        }
    }
}

Ver la lógica de implementación del código fuente subyacente
Inserte la descripción de la imagen aquí

Determine el tipo de colección de lista entrante, determine si el tipo es java.util.RandomAccess, si lo es, use el java.util.Collections.SynchronizedRandomAccessListconjunto de construcción, si no, use el java.util.Collections.SynchronizedListconjunto de construcción.

La lógica de operación de adición correspondiente en el código fuente es la siguiente:
Inserte la descripción de la imagen aquí

¡Tome synchronizedla forma de sincronizar el bloque de código y realice el bloqueo en la operación de adición de los datos!

  • Método 2: nuevo CopyOnWriteArrayList ();
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class ListTest {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        List<String> lists = new CopyOnWriteArrayList<>();

        // 开启十个线程增加数据
        for (int i = 1; i <= 40; i++) {
    
    
            new Thread(()->{
    
    
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+lists);
            },String.valueOf(i)).start();
        }
    }
}

La introducción en el código fuente es la siguiente:
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Obviamente, la lógica es la siguiente:

1. Después de llamar al método add, obtenga la java.util.concurrent.locks.ReentrantLockinformación del objeto.
2, ¡llama lock.lock()para conseguir un candado!
3. Copie el objeto de matriz original y cree una nueva matriz con el tamaño de la matriz original +1.
4. Coloque los nuevos datos en la nueva matriz.
5. ¡Para cualquier operación finalmente, el bloqueo se libera!

Aspecto de rendimiento

¡La operación de bloqueo en el paquete JUC tiene un mejor rendimiento que la sincronización!

Supongo que te gusta

Origin blog.csdn.net/qq_38322527/article/details/114703142
Recomendado
Clasificación