util que ejemplo java queue

java - ejemplo - ¿Dónde debería usar las implementaciones de BlockingQueue en lugar de las implementaciones de Simple Queue?



blockingqueue java ejemplo (4)

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?

a

¿Cuáles son las ventajas / desventajas de las implementaciones de BlockingQueue sobre Queue teniendo en cuenta aspectos como la velocidad, la concurrencia u otras propiedades que varían, por ejemplo, el tiempo de acceso 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 hablar sobre los pros y los contras de las implementaciones BlockingQueue vs Queue vs List?

Actualmente he usado ArrayList para contener estos objetos ByteBuffer.

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


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


Una capacidad limitada de 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 dado por vencido hace mucho tiempo, por lo que el esfuerzo se desperdicia.

En situaciones como estas, puede ser mejor indicarle 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.

Con respecto a la pregunta modificada, que estoy interpretando como, "¿Qué es una buena colección para contener objetos en un grupo?"

Un LinkedBlockingQueue ilimitado 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 agrupación, un "poner" bloqueado 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 "captura" que se bloquea, al menos temporalmente, es mucho más eficiente que una "espera ocupada", sondeando repetidamente hasta que haya un recurso disponible. La 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 la poll .

Un caso menos común en el que un cliente no está dispuesto a bloquear en absoluto, pero tiene la capacidad de crear un recurso para sí mismo si el grupo está vacío. En ese caso, una ConcurrentLinkedQueue es una buena opción. Esta es una especie de área gris donde 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 brindan un buen rendimiento y facilidad de uso en una aplicación simultánea. Para aplicaciones no concurrentes, ArrayList es difícil de superar. Incluso para las colecciones que crecen dinámicamente, la sobrecarga por elemento de una LinkedList permite que una ArrayList con algunas ranuras vacías se mantenga competitiva en cuanto a la memoria.


BlockingQueue también es útil para serializar operaciones paralelas que dependen unas de otras.

Para traer un ejemplo concreto (aunque algo arbitrario), aquí hay una prueba paralela para una aplicación web de cola de pacientes en tiempo real donde callInPatient() necesita callInPatient() en paralelo con registerPatientToAppointment() , pero necesita esperar hasta que registerPatientToAppointment() se complete antes ejecutando 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); } }


Es una implementación de Queue que también admite operaciones que

espere a que la cola se vuelva no vacía al recuperar un elemento,

y

espere a que haya espacio disponible en la cola al almacenar un elemento.

Si requirió la funcionalidad anterior, será seguida por su implementación de Queue luego use la Blocking Queue