No es difícil ejecutar un programa; ¡lo difícil es qué tan lejos puede ejecutarse el programa! —— una semilla feroz
Serie de concurrencia JUC
Serie de concurrencia JUC (1): ¿Qué? Escuché que confunde concurrencia y
serie de concurrencia JUC paralela (2): Explicación detallada de la condición para lograr una notificación precisa para despertar
Serie de concurrencia JUC (3): concurrencia en la entrevista, cuando se le pregunte sobre el bloqueo, quedará atónito. )
Uno, ArrayList no es seguro para subprocesos
En la serie anterior de subprocesos múltiples, se mencionó que ArrayList no es seguro en subprocesos múltiples.
No importa si no lo ha visto antes, saquemos el código y lo revisemos.
1.1 Ejemplo de código no seguro para subprocesos de ArrayList
public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
resultado de la operación
Puede ver que el número de adiciones a la longitud de la colección no es la que esperábamos.
En su lugar, puede producirse una sobrescritura.
No es seguro recopilar ArrayList en varios subprocesos.
Dos, Vector resuelve la seguridad sin subprocesos de ArrayList
¿No es curioso, por qué se menciona Vector aquí, no solo porque Vector es seguro para subprocesos, sino también porque ArrayList proviene de la interfaz List, por lo que puede ser el que se encuentra con más frecuencia cuando aprende, o puede ser la solución más común para los problemas de no subprocesos de ArrayList en su desarrollo Por supuesto, también se usarán comúnmente las respuestas de la entrevista que suelte.
Pero pero...
Si solo conoces Vector, no es suficiente. ¿Por qué dices eso? ¡Solo una pequeña pregunta!
¿Crees que ArrayList fue el primero en JDK o Vector ?
Su respuesta debe ser ArrayList primero y luego Vector . Todavía hay una pregunta. Vector no está destinado a resolver el problema de no subprocesamiento de ArrayList.
Pero la respuesta puede ser la opuesta: Vector se agregó en JDK1.0 , mientras que ArrayList se agregó en JDK1.2. Entonces, Vector es viejo y ArrayList es el nuevo (por supuesto, 1.2 no es nuevo).
2.1 Vector resuelve el ejemplo de código no subproceso de ArrayList
Vector es muy simple de resolver, simplemente reemplace la palabra clave ArrayList con Vector.
Vector<String> list = new Vector<String>();
Vector excepto
public class Demo {
public static void main(String[] args) {
Vector<String> list = new Vector<String>();
for (int i = 0; i < 10000; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
resultado de la operación
2.2 Vector es bueno, pero utilícelo con precaución
Aunque Vector es una lista segura para subprocesos, su implementación segura para subprocesos consiste en agregar la palabra clave sincronizada a todas las operaciones. Este método afecta seriamente la eficiencia. Por lo tanto, no se recomienda Vecto.
2.3 La respuesta de la entrevista a Vector no es un elemento adicional, solo una respuesta
Además de usarlo con precaución, cuando se reúna en una entrevista, si solo responde a Vector, en realidad no le dará puntos adicionales, porque Vector es una palabra clave antigua y solo puede considerarse como una respuesta.
Pero si puede responder a Vector y decir las siguientes soluciones, entonces puede reflejar la amplitud de su conocimiento.
Tres, synchronizedList resuelve la seguridad sin subprocesos de ArrayList
SynchronizedList es un método proporcionado por Collections, también es muy simple de resolver.
List<String> list = Collections.synchronizedList(new ArrayList());
3.1 SynchronizedList resuelve el ejemplo de código no subproceso de ArrayList
public class Demo {
public static void main(String[] args) {
List<String> list = Collections.synchronizedList(new ArrayList());
for (int i = 0; i < 10000; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
resultado de la operación
3.2 Ventajas y desventajas de synchronizedList
El rendimiento de la operación de escritura de synchronizedList es mucho mejor que el de CopyOnWriteArrayList que se describe a continuación en la operación de subprocesos múltiples, pero la operación de lectura usa la palabra clave sincronizada, por lo que es mejor leer que CopyOnWriteArrayList.
Mientras haya un lugar sincronizado, es decir, haya un lugar para bloquear, por supuesto, no hay una buena forma de hacerlo en términos de rendimiento.
Por lo tanto, no existe la mejor manera, solo los escenarios de aplicación más adecuados.
Cuatro, CopyOnWriteArrayList
CopyOnWriteArrayList se encuentra principalmente en CopyOnWrite copy-on-write (COW para abreviar), que es una estrategia de optimización en programación de computadoras.
La idea de copiar en escritura es que cuando varios subprocesos leen el mismo recurso al mismo tiempo, obtendrán conjuntamente el recurso al que apunta el puntero, pero cuando algunos subprocesos operan (modifican) el mismo recurso, en realidad harán una copia, mientras que otros El acceso del subproceso al recurso inicial permanece sin cambios.
Se puede entender simplemente que evitar sobrescribir cuando la escritura de datos causó problemas.
4.1 CopyOnWriteArrayList resuelve el ejemplo de código no subproceso de ArrayList
public class Demo {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
resultado de la operación
4.2 Resumen CopyOnWriteArrayList
En base a lo anterior, creo que puede resumir CopyOnWriteArrayList, CopyOnWriteArrayList es mejor que Vector y synchronizedList en lectura, pero el rendimiento de lectura y escritura no es tan bueno como synchronizedList.
Cinco, finalmente
Al final, para una mejor experiencia de lectura, pongo todo lo que quiero decir a continuación, jeje.
Soy semilla de decisiones basadas en mi voluntad, en serio compartir lo que escribí en el blog ha sido el mismo credo.
Si puedes leer esta entrada del blog, significa que todavía estamos muy destinados; espero que te pueda traer algo de ayuda, la creación no es fácil, quita el conocimiento de mi artículo, tus tres seguidos dejan, me gusta, comenta, sigue , Es mi mayor motivación.