2011-08-02 10 views
159

¿Cómo puedo crear una instancia de lista simultánea, donde puedo acceder a los elementos por índice? ¿El JDK tiene alguna clase o método de fábrica que pueda usar?¿Hay una lista concurrente en el JDK de Java?

+18

Por qué no constructiva? Varios propusieron CopyOnWriteArrayList que no se encuentra en .Net. ¡Puedes decir que ambas preguntas se relacionan entre ellas pero no para cerrarla! –

+0

En .NET, el equivalente de CopyOnWriteArrayList son las colecciones inmutables. Una colección simultánea es aquella que no requiere bloqueo para modificar (como ConcurrentQueue, etc.), NO una que copia su contenido cada vez que se copia. –

+1

No tengo idea de por qué Jarrod Roberson pensaría que era una buena idea tomar las ediciones detalladas hechas por Stephan y revertirlas a la pregunta original mal formulada. La respuesta de Jarrod sigue siendo perfectamente aceptable. De hecho, CopyOnWriteArrayList es la única clase simultánea que implementa List en el JDK. Desconcertado ... –

Respuesta

112

Hay una implementación de lista concurrente en java.util.concurrent. CopyOnWriteArrayList en particular.

+53

Tenga en cuenta que copia la lista completa en cada inserción, por lo que a menudo es ineficiente. – dfrankow

+11

@dfrankow Pero puede ser más * más * eficiente si está iterando mucho más de lo que está actualizando. –

30

Porque el acto de adquirir la posición y obtener el elemento desde la posición dada requiere naturalmente un bloqueo (no puede tener la lista tiene cambios estructurales entre esas dos operaciones).

La idea misma de una colección simultánea es que cada operación en sí misma es atómica y puede realizarse sin bloqueo/sincronización explícitos.

Por lo tanto conseguir el elemento en la posición de un determinado nList como una operación atómica no tiene mucho sentido en una situación en la que se prevé el acceso concurrente.

+4

Joachim, creo que le pegaste al clavo en la cabeza. Tomemos, por ejemplo, una lista de solo lectura como una lista concurrente. Obtener el elemento en la posición N de la lista no solo tiene sentido, sino que es la cáscara del problema. Entonces, una lista inmutable (minúscula L) sería un buen ejemplo, pero no es una Lista (mayúscula L). CopyOnWriteArrayList es concurrente, pero a muchas personas no les gusta el rendimiento. Una solución a lo largo de las líneas de cuerdas (cuerdas de cuerdas) probablemente sería un buen ganador. – johnstosh

+0

Muy buen punto. Pero la lista que utiliza el OP podría tener un uso muy específico. P.ej. podría llenarse en un entorno concurrente, luego "bloquearse" (lo que sea que signifique) y luego accederse de manera segura por índice. Por lo tanto, en la primera fase de llenado, dicha Lista aún requerirá una implementación segura para subprocesos. Desafortunadamente, el PO no fue específico sobre cómo se usará la Lista que está buscando. –

90

Puede utilizar muy bien Collections.synchronizedList(List) si todo lo que necesita es una sincronización sencilla invocación:

List<Object> objList = Collections.synchronizedList(new ArrayList<Object>()); 
+43

El resultado de 'synchronizedList' es" sincronizado "pero no" concurrente ". Un problema fundamental es que muchas operaciones de listas, que están basadas en índices, en sí mismas no son atómicas y deben formar parte de una construcción de exclusión mutua más amplia. –

+3

IMO, asing a 'Vector' es más sencillo en lugar de' Collections.synchronizedList (new ArrayList ()) '. – Stephan

+4

El resultado de synchronizedList es "sincronizado" pero no "concurrente". –

95

Si no se preocupan por tener acceso basado en el índice y sólo desea la inserción orden de preservación de las características de una Lista, puede considerar un java.util.concurrent.ConcurrentLinkedQueue. Ya que implementa Iterable, una vez que haya terminado de añadir todos los elementos, puede recorrer a través de los contenidos utilizando el simplificada para-cada sintaxis:

Queue<String> globalQueue = new ConcurrentLinkedQueue<String>(); 

//Multiple threads can safely call globalQueue.add()... 

for (String href : globalQueue) { 
    //do something with href 
} 
+3

Creo que la declaración simplificada for (':') se llama foreach: http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html –

+2

@ AlikElzin-kilaka Estás derecho. Creo que ese nombre siempre me ha molestado, porque la sintaxis actual no incluye la palabra "cada", pero actualizaré la respuesta para usar el nombre oficial. :) –

+2

@ AlikElzin-kilaka Nitpicking, pero de acuerdo con [JLS versión 8] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2) se llama "declaración mejorada". Lo mismo en el [tutorial de Java] (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html). – Roland