English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
La implementación de la interfaz List de arrays de tamaño variable. Implementa todas las operaciones listas opcionales y permite todos los elementos, incluyendo null. Además de implementar la interfaz List, este tipo proporciona algunos métodos para operar con el tamaño del array utilizado internamente para almacenar la lista. (Este tipo es aproximadamente equivalente a la clase Vector, excepto que este no es sincronizado.) Las operaciones size, isEmpty, get, set, iterator y listIterator se ejecutan en tiempo fijo. La operación add se ejecuta en tiempo fijo distribuido, lo que significa que agregar n elementos toma tiempo O(n). Todas las otras operaciones se ejecutan en tiempo lineal (hablando en términos generales). En comparación con los factores constantes utilizados en la implementación de LinkedList, este tipo tiene factores constantes más bajos. Cada instancia de ArrayList tiene una capacidad. La capacidad es el tamaño del array utilizado para almacenar los elementos de la lista. Siempre es al menos igual al tamaño de la lista. A medida que se agregan elementos a ArrayList, su capacidad también aumenta automáticamente. No se especifican los detalles de la estrategia de crecimiento porque no es tan simple como la carga de tiempo fijo distribuido que se asocia con agregar elementos. Antes de agregar muchos elementos, la aplicación puede usar la operación ensureCapacity para aumentar la capacidad de la instancia de ArrayList. Esto puede reducir el número de redistribuciones incrementales.
Tenga en cuenta que esta implementación no es sincronizada.
Si varios hilos acceden simultáneamente a una instancia de ArrayList y al menos uno de ellos realiza modificaciones estructurales en la lista, debe mantener la sincronización externa. (Las modificaciones estructurales incluyen cualquier operación de agregar o eliminar uno o más elementos, o ajustar explícitamente el tamaño del array subyacente; solo establecer el valor de un elemento no es una modificación estructural.) Esto generalmente se realiza mediante operaciones de sincronización sobre el objeto que naturalmente encapsula la lista. Si no existe tal objeto, debe usar el método Collections.synchronizedList para encapsular la lista. Esto es mejor hacer en el momento de la creación para evitar accesos inesperados no sincronizados a la lista:
Listlist=Collections.synchronizedList(newArrayList(...));
Los métodos iterator y listIterator de este tipo devuelven iteradores de falla rápida: después de crear el iterador, a menos que se modifique la estructura de la lista mediante los métodos remove o add del propio iterador, cualquier modificación de la lista en cualquier momento y de cualquier manera provocará la excepción ConcurrentModificationException. Por lo tanto, frente a modificaciones concurrentes, el iterador fallará rápidamente en lugar de arriesgarse a comportamientos no determinados en algún momento futuro indeterminado.
Atención, no se puede garantizar el comportamiento de falla rápida del iterador, porque generalmente es imposible hacer garantías estrictas sobre la aparición o no de modificaciones concurrentes des sincronizadas. El iterador de falla rápida intentará arrojar ConcurrencyModificationException con todo su esfuerzo. Por lo tanto, escribir un programa que dependa de esta excepción para aumentar la precisión de estos iteradores es un error: el comportamiento de falla rápida del iterador debe usarse solo para detectar errores.
Como se muestra anteriormente, ahora se crea una colección list, una hebra realiza operaciones de escritura en la colección, y otra hebra realiza operaciones de eliminación
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * Crear una lista, un hilo para escribir y otro para leer; los métodos iterator y listIterator devueltos por el iterador son rápidos y fallan */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //iniciar hilo de escritura new WriteListThread(synNums).start(); //iniciar hilo de eliminación new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super(“WriteListThread”); this.nums = nums; } // escribir elementos sin parar1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super(“DeleteListThread”); this.nums = nums; } // eliminar el primer elemento public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName()+:"+nums.remove(0)); } catch(Exception e){ continue ; } } } }
A través de List<Integer> synNums = Collections.synchronizedList(nums); se puede realizar la sincronización de operaciones atómicas, pero ¿por qué el ejemplo de API oficial requiere agregar la sincronización manualmente?
List list = Collections.synchronizedList(new ArrayList()); synchronized(list) { Iterator i = list.iterator(); // Debe estar en un bloque sincronizado while (i.hasNext()) foo(i.next()); }
Ver el código fuente de Collections.synchronizedList
SynchronizedCollection(Collection<E> c) { if (c==null) throw new NullPointerException(); this.c = c; mutex = this; }
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * Crear una lista, un hilo para escribir y otro para leer; los métodos iterator y listIterator devueltos por el iterador son rápidos y fallan */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //iniciar hilo de escritura new WriteListThread(synNums).start(); //iniciar hilo de eliminación new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super("WriteListThread"); this.nums = nums; } // escribir elementos sin parar1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super("DeleteListThread"); this.nums = nums; } // eliminar el primer elemento public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName()+:+nums.remove(0)); } catch(Exception e){ continue ; } } } }
Se puede ver que para las operaciones de sincronización de la colección, además de usar la herramienta de envoltura de sincronización de Collections, los usuarios también deben realizar la sincronización manualmente para las operaciones no atómicas
Como se muestra a continuación, se agrega un hilo para leer la colección
class ReadListThread extends Thread { private List<Integer> nums; public ReadListThread(List<Integer> nums) {}} super(“ReadListThread”); this.nums = nums; } // Leer elementos constantemente, operaciones no atómicas, por lo que se debe agregar manualmente el candado public void run() { while (true) { //Dormir, entregar el candado a otro hilo try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } synchronized (nums) { if (nums.size() > 100) { Iterator<Integer> iter = nums.iterator(); while (iter.hasNext()) { System.out.println(Thread.currentThread().getName() + :" + iter.next()); ; } } else{ try { nums.wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
Resumen
Esto es todo el contenido detallado sobre el código de sincronización de hilos de la estructura de colecciones de Java en este artículo, espero que sea útil para todos. Los amigos interesados pueden continuar consultando otros temas relacionados en este sitio, y si hay algo que no esté bien, por favor déjenos un mensaje. Gracias por el apoyo de los amigos a este sitio!
Declaración: El contenido de este artículo se obtiene de la red, es propiedad del autor original, el contenido se contribuye y carga de manera autónoma por los usuarios de Internet, este sitio no posee los derechos de propiedad, no se ha realizado un procesamiento editorial humano y no asume ninguna responsabilidad legal relacionada. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, reemplace # con @) para denunciar y proporcionar evidencia relevante. Una vez confirmado, este sitio eliminará inmediatamente el contenido sospechoso de infracción.