Directorio de artículos
Prefacio
La colección de conjuntos está intrínsecamente desordenada en Java, y hay una explicación muy detallada en el código fuente subyacente sobre por qué está desordenada.
En esencia, sigue siendo una HashMap
colección que contiene la forma en que se guardan los datos en la clave.
Para obtener más detalles sobre por qué es el desorden, puede consultar el contenido de otro blog ( código fuente java - análisis del código fuente hashmap (jdk1.8) ), y no lo explicaré aquí.
¿Por qué no es segura la recopilación de conjuntos normal en subprocesos múltiples?
Como se menciona en el título, ¿por qué la colección de conjuntos es insegura bajo la condición de ejecución multiproceso? Veamos el siguiente caso de código:
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class SetTest {
public static void main(String[] args) throws InterruptedException {
// 不安全
Set<String> sets = new HashSet();
for (int i = 1; i <= 40; i++) {
new Thread(()->{
sets.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName()+"=="+sets);
},String.valueOf(i)).start();
}
}
}
Cuando una operación de subprocesos múltiples con una colección determinada de objetos, todavía parece aumentar las java.util.ConcurrentModificationException
anomalías de datos .
Colecciones seguras bajo Colecciones
Al igual que la forma de crear un conjunto seguro para List en la clase de herramienta de colección Colecciones, también proporciona una forma de crear una colección de conjuntos segura.
import java.util.*;
public class SetTest {
public static void main(String[] args) throws InterruptedException {
// 不安全
//Set<String> sets = new HashSet();
Set<String> sets = Collections.synchronizedSet(new HashSet<>());
for (int i = 1; i <= 40; i++) {
new Thread(()->{
sets.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName()+"=="+sets);
},String.valueOf(i)).start();
}
}
}
El código fuente es similar a la colección de listas:
también se agrega al método de ejecución de la operación de adición para synchronized 同步代码块
garantizar la seguridad de operar la colección de conjuntos en múltiples subprocesos.
Colección de conjuntos de seguridad bajo JUC
También jdk 1.5
más adelante, juc para la colección de conjuntos también proporciona clases de colección de conjuntos de seguridad. Como sigue:
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
public class SetTest {
public static void main(String[] args) throws InterruptedException {
// 不安全
//Set<String> sets = new HashSet();
//Set<String> sets = Collections.synchronizedSet(new HashSet<>());
Set<String> sets = new CopyOnWriteArraySet<>();
for (int i = 1; i <= 40; i++) {
new Thread(()->{
sets.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(Thread.currentThread().getName()+"=="+sets);
},String.valueOf(i)).start();
}
}
}
La lógica del código fuente es la siguiente:
Y CopyOnWriteArrayList
de tal manera que se aproveche java.util.concurrent.locks.ReentrantLock
para lograr bloquear y desbloquear cerraduras y otras operaciones.
1. Después de llamar al método add, obtenga la información del objeto java.util.concurrent.locks.ReentrantLock.
2. ¡Llame a lock.lock () para obtener el bloqueo!
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, se libera el bloqueo.