java.util.ConcurrentLinkedQueue
tomcat servlets (4)
Quiero usar java.util.ConcurrentLinkedQueue como una cola no duradera para un servlet. Aquí está la propaganda del javadoc para la clase.
Una cola ilimitada sin hilos basada en nodos vinculados. Una ConcurrentLinkedQueue es una opción adecuada cuando muchos hilos compartirán el acceso a una colección común. Esta cola no permite elementos nulos.
Ahora imagine que tengo 1000 solicitudes simultáneas en el servlet, y cada subproceso tendrá que poner un objeto en ConcurrentLinkedQueue. De la descripción, ¿debo concluir que no tendrá problemas para manejar la carga? La garantía que necesitaré es que:
- Recibo automáticamente la garantía de subprocesos sin necesidad de hacer mi propia sincronización.
- No perderé ninguna solicitud si la carga del tráfico va más allá de 1000 solicitudes simultáneas.
Gracias
Dado que la cola es segura para subprocesos, no necesita realizar ninguna sincronización para garantizar la seguridad de subprocesos. Sin embargo, debe asegurarse de que todos los hilos tengan el mismo acceso a la cola para evitar el hambre, la espera de ocupados, etc.
Como la cola no tiene límites, el tamaño de la cola está limitado solo por la cantidad de memoria que tiene disponible.
Básicamente estás haciendo tres preguntas diferentes (dos de ellas explícitamente y otra implícitamente). Aquí están, con mis respuestas:
1. ¿Debo hacer mi propia sincronización si uso java.util.ConcurrentLinkedQueue
?
Las operaciones atómicas en las colecciones simultáneas están sincronizadas para usted. En otras palabras, cada llamada individual a la cola está garantizada por subprocesos sin ninguna acción de su parte. Lo que no está garantizado para seguridad de subprocesos son las operaciones que realice en la colección que no sean atómicas.
Por ejemplo, esto es seguro para la realización de hilos sin ninguna acción de su parte:
queue.add(obj);
o
queue.poll(obj);
Sin embargo; Las llamadas no atómicas a la cola no son automáticamente seguras para subprocesos. Por ejemplo, las siguientes operaciones no son automáticamente seguras en cuanto a los hilos:
if(!queue.isEmpty()) {
queue.poll(obj);
}
El último no es inseguro, ya que es muy posible que, entre el momento en que se invoque Vacíe y se llame a la encuesta de tiempo, otros hilos hayan agregado o eliminado elementos de la cola. La forma segura de realizar esto es así:
synchronized(queue) {
if(!queue.isEmpty()) {
queue.poll(obj);
}
}
De nuevo ... las llamadas atómicas a la cola son automáticamente seguras para subprocesos. Las llamadas no atómicas no lo son.
2. ¿Tengo la garantía de no perder llamadas a java.util.ConcurrentLinkedQueue
si hay 1000 solicitudes simultáneas?
Como se trata de una implementación ilimitada, se garantiza que, independientemente de la cantidad de solicitudes simultáneas que se realicen, la cola no perderá esas solicitudes (debido a la concurrencia de la cola ... es posible que se quede sin memoria o algo así ... pero la cola la implementación en sí misma no será su factor limitante). En una aplicación web, hay otras oportunidades para "perder" solicitudes, pero la sincronización (o la falta de ellas) de la cola no será su causa.
3. ¿ java.util.ConcurrentLinkedQueue
el java.util.ConcurrentLinkedQueue
suficientemente bien?
Por lo general, hablamos de "corrección" cuando hablamos de concurrencia. Lo que quiero decir es que las clases concurrentes garantizan que son seguras para subprocesos (o robustas frente a dead-lock, inanición, etc.) Cuando hablamos de eso, no estamos garantizando el rendimiento (qué tan rápido llama a la colección son) - solo garantizamos que son "correctos".
Sin embargo; el ConcurrentLinkedQueue es una implementación "libre de espera", por lo que probablemente sea tan eficiente como puedas obtener. La única manera de garantizar el rendimiento de la carga de su servlet (incluido el uso de las clases concurrentes) es probarlo bajo carga.
Recuerde que la cola solo es segura para las llamadas a un único miembro. No escriba código como este y espere que funcione:
if (queue.Count!=0)
queue.Dequeue().DoSomething();
Entre estas dos operaciones, otro hilo puede haber quitado el último elemento. No estoy familiarizado con las colecciones de Java, pero supongo que Dequeue en ese caso devolvería null
, brindándote una excepción.
Sí, para sus dos preguntas.
La cola simultánea es segura para subprocesos (y es eficiente debido al algoritmo sin bloque utilizado debajo). Thread-safe implica que el número de accesos concurrentes no debe hacer ninguna diferencia (todavía no he oído hablar de una condición de carrera que está garantizada que no ocurra por debajo de los accesos simultáneos xyz).
Aparte de eso, el rendimiento óptimo en aplicaciones de subprocesos múltiples es más complejo que eso. Pero usar una colección concurrente real no es un mal comienzo.