2008-12-11 12 views
16

Creo que voy a replantear mi pregunta de¿Dónde debería usar las implementaciones de BlockingQueue en lugar de las implementaciones de Simple Queue?

¿Dónde debería utilizar las implementaciones de BlockingQueue en lugar de las implementaciones de Simple Queue?

a

cuáles son las ventajas/desventajas de BlockingQueue más de las implementaciones de cola que toman en consideración aspectos como la velocidad, la concurrencia u otras propiedades que varían, por ejemplo, tiempo para acceder al último elemento

He usado ambos tipos de colas. Sé que Blocking Queue se usa normalmente en aplicaciones concurrentes. Estaba escribiendo un conjunto simple de ByteBuffer donde necesitaba un marcador de posición para objetos ByteBuffer. Necesitaba la implementación de cola más rápida y segura para hilos. Incluso hay implementaciones de List como ArrayList que tiene tiempo de acceso constante para los elementos.

¿Alguien puede discutir sobre los pros y contras de las implementaciones de BlockingQueue vs Queue vs List?

Actualmente he usado ArrayList para guardar estos objetos ByteBuffer.

¿Qué estructura de datos debo usar para contener estos objetos?

Respuesta

26

Una capacidad limitada BlockingQueue también es útil si desea acelerar algún tipo de solicitud. Con una cola sin límites, los productores pueden adelantarse mucho a los consumidores. Las tareas eventualmente se realizarán (a menos que haya tantas que causen un OutOfMemoryError), pero el productor puede haberse rendido hace mucho tiempo, por lo que el esfuerzo se desperdicia.

En situaciones como estas, puede ser mejor indicar a un posible productor que la cola está llena y renunciar rápidamente con una falla. Por ejemplo, el productor podría ser una solicitud web, con un usuario que no quiere esperar demasiado, y aunque no consumirá muchos ciclos de CPU mientras espera, está usando recursos limitados como un socket y algo de memoria. . Renunciar dará a las tareas que se han puesto en cola ya una mejor oportunidad de terminar de manera oportuna.


En cuanto a la pregunta modificada, que estoy interpretando como, "¿Qué es una buena colección para sostener objetos en una piscina?"

Un ilimitado LinkedBlockingQueue es una buena opción para muchas piscinas. Sin embargo, dependiendo de la estrategia de administración de su grupo, también puede funcionar un ConcurrentLinkedQueue.

En una aplicación de agrupamiento, un "bloqueo" de bloqueo no es apropiado. Controlar el tamaño máximo de la cola es el trabajo del administrador de la agrupación —. Decide cuándo crear o destruir recursos para la agrupación. Los clientes de la agrupación piden prestado y devuelven recursos del grupo. Agregar un nuevo objeto o devolver un objeto previamente prestado al grupo debe ser operaciones rápidas y sin bloqueos. Por lo tanto, una cola de capacidad limitada no es una buena opción para las agrupaciones.

Por otro lado, al recuperar un objeto del grupo, la mayoría de las aplicaciones desean esperar hasta que haya un recurso disponible. Una operación de "toma" que bloquea, al menos temporalmente, es mucho más eficiente que una "espera ocupada" — sondeando varias veces hasta que haya un recurso disponible. El LinkedBlockingQueue es una buena opción en este caso. Un prestatario puede bloquear indefinidamente con take o limitar el tiempo que está dispuesto a bloquear con poll.

Un caso menos común en cuando un cliente no está dispuesto a bloquear en absoluto, sino que tiene la capacidad de crear un recurso por sí mismo si la piscina está vacía. En ese caso, un ConcurrentLinkedQueue es una buena opción. Esta es una especie de área gris en la que sería bueno compartir un recurso (por ejemplo, memoria) tanto como sea posible, pero la velocidad es aún más importante. En el peor de los casos, esto degenera a cada hilo que tiene su propia instancia del recurso; entonces habría sido más eficiente no molestarse en tratar de compartir entre hilos.

Ambas colecciones proporcionan un buen rendimiento y facilidad de uso en una aplicación simultánea. Para aplicaciones no concurrentes, un ArrayList es difícil de superar. Incluso para las colecciones que crecen de forma dinámica, la sobrecarga por elemento de un LinkedList permite una ArrayList con algunos espacios vacíos para mantenerse en memoria sabia competitiva.

+1

Gracias Erickson para una buena explicación. Ha resuelto mi problema. –

2

Vería BlockingQueue en situaciones de subprocesos múltiples. Por ejemplo, necesita pasar en un BlockingQueue como parámetro para crear ThreadPoolExecutor si desea crear uno usando el constructor. Dependiendo del tipo de cola que pase, el ejecutor podría actuar de manera diferente.

0

BlockingQueue es también útil para serializar operaciones paralelas que dependen unos de otros.

para llevar un concreto (aunque algo arbitraria) ejemplo, here es un ensayo paralelo para una aplicación web cola de paciente en tiempo real, donde callInPatient() necesita para poner en marcha en paralelo con registerPatientToAppointment(), pero hay que esperar hasta registerPatientToAppointment() se complete antes de ejecutar callPatientInAtDoctorsOffice() :

public class ClinicPatientQueueAppTest extends ParallelTest { 

    private static final BlockingQueue WAIT_FOR_REGISTRATION_QUEUE = new ArrayBlockingQueue(2); 

    @Test 
    public void callInPatient() { 
     loginToDoctorsOffice("user", "password"); 
     waitUntilRegistrationCompleted(); // <-- 
     callPatientInAtDoctorsOffice(); 
    } 

    @Test 
    public void registerPatientToAppointment() { 
     registerPatientAtRegistrationKiosk("Patient Peter"); 
     notifyRegistrationCompleted(); // <-- 
    } 

    private void waitUntilRegistrationCompleted() { 
     WAIT_FOR_REGISTRATION_QUEUE.take(); 
    } 

    private void notifyRegistrationCompleted() { 
     WAIT_FOR_REGISTRATION_QUEUE.put(this); 
    } 

} 
0

es una aplicación Queue que, además, apoya operaciones que

de espera para la cola de convertido no vacía al recuperar un elemento,

y

espera para el espacio que estén disponibles en la cola al almacenar un elemento .

Si requerida por encima de la funcionalidad será seguido por su aplicación Queue a continuación, utilizar Blocking Queue

Cuestiones relacionadas