Bloqueo de colas en Java
1. ¿Qué es una cola de bloqueo?
Una cola de bloqueo (Bloquingqueue) es una cola que admite dos operaciones adicionales. Estas dos operaciones adicionales son:
Cuando la cola está vacía, el hilo que obtiene el elemento esperará a que la cola no se vea vacía.
Cuando la cola está llena, el hilo que almacena los elementos esperará a que la cola esté disponible.
Las colas de bloqueo a menudo se usan en escenarios de productores y consumidores. Los productores son hilos que agregan elementos a las colas, y los consumidores son hilos que toman elementos de las colas. Una cola de bloqueo es el contenedor donde el productor almacena elementos, y el consumidor solo toma elementos del contenedor.
2. Bloqueo de la cola en Java
Se proporcionan siete colas de bloqueo en el JDK:
Arrayblockingqueue
ArrayBlockingqueue es una cola de bloqueo limitada implementada utilizando matrices. Esta cola clasifica los elementos de acuerdo con el principio de primera vez (FIFO). Por defecto, los visitantes no están garantizados para acceder de manera justa. La llamada cola bastante accesible se refiere a todos los hilos de productores bloqueados o hilos de consumo. Cuando la cola está disponible, se puede acceder a la cola en el orden del bloqueo. Es decir, el hilo del productor que bloquea primero primero los elementos en la cola primero, y el hilo del consumidor que bloquea primero puede obtener elementos de la cola primero. Normalmente, el rendimiento se reduce para garantizar la equidad . Podemos crear una cola de bloqueo justo utilizando el siguiente código:
ArrayBlockingqueue Fairqueue = New ArrayBlockingqueue (1000, verdadero);
La justicia de su acceso se logra a través del bloqueo de reentrantamiento.
LinkedBlokingqueue
Linked Bloquingqueue es una cola de bloqueo limitada implementada con listas vinculadas. La longitud predeterminada y máxima de esta cola es entero.max_value. Esta cola clasifica elementos de acuerdo con el principio de primera en salida.
Priorityblockingqueue
PriorityBlockingqueue es una cola ilimitada que respalda la prioridad. Por defecto, los elementos se organizan en orden natural, y las reglas de pedido de elementos también se pueden especificar a través del comparador del comparador. Los elementos están organizados en orden ascendente.
Retraso
Delayqueue es una cola de bloqueo ilimitada que respalda la adquisición tardía de elementos. La cola se implementa utilizando priorityqueue. Los elementos en la cola deben implementar la interfaz retrasada, y al crear un elemento, puede especificar cuánto tiempo lleva obtener el elemento actual de la cola. Los elementos solo se pueden extraer de la cola cuando expira el retraso. Podemos usar DelayQueue en los siguientes escenarios de aplicación:
Diseño del sistema de caché: Delayqueue se puede utilizar para ahorrar el período de validez de los elementos de caché, y se puede usar un hilo para consultar el Delayqueue. Una vez que el elemento se puede obtener de Delayqueue, significa que ha llegado el período de validez del caché.
Programación de tareas programado. Use Delayqueue para guardar las tareas y el tiempo de ejecución que se ejecutará en el día. Una vez que la tarea se obtenga de Delayqueue, comenzará a ejecutarse. Por ejemplo, TimerQueue se implementa utilizando Delayqueue.
Cómo implementar la interfaz retrasada
Podemos referirnos a la clase ProchuledFutureTask en ProchuledThreadPoolExecutor. Esta clase implementa la interfaz retrasada. Primero: al crear un objeto, use el tiempo para grabar cuando el objeto se puede usar antes de grabar. El código es el siguiente:
ProchuledFutureTask (Runnable R, V Result, Long Ns, Long Period) {super (r, resultado); this.time = ns; this.period = período; this.SequencEnumber = SECHENCER.GETAndIrcrement ();}Luego use GetDelay para consultar cuánto tiempo debe retrasarse el elemento actual. El código es el siguiente:
public Long GetDelay (Unidad de TimeUnit) {Return Unit.convert (Time - Now (), TimeUnit.nanoseConds); }A través del constructor, podemos ver que la unidad del parámetro de tiempo de retraso NS es nanosegundos. Es mejor usar nanosegundos al diseñarlo usted mismo, ya que puede especificar cualquier unidad al obtenerlo. Una vez que se usan nanosegundos como unidad, y el tiempo de retraso es menor que los nanosegundos, será problemático. Cuando use, tenga en cuenta que cuando el tiempo sea menor que la hora actual, GetDelay devolverá un número negativo.
Finalmente, podemos usar el tiempo para especificar el pedido en la cola, por ejemplo: deje que el tiempo de retraso más largo se coloque al final de la cola.
public int Compareto (retrasado otro) {if (otro == this) return 0; if (otra instancia de programadofutureTask) {ProchuledFutureTask x = (ProchuledFutureTask) otro; larga diff = tiempo - x.time; if (diff <0) return -1; else if (diff> 0) return 1; else if (secuenceNumber <x.SequencEnumber) return -1; de lo contrario regresar 1; } long d = (getDelay (timeUnit.nanoseConds) -Ots.getDelay (TimeUnit.nanoseConds)); return (d == 0)? 0: ((d <0)? -1: 1); }Cómo implementar colas de bloqueo retrasado
La implementación de las colas de bloqueo de demora es muy simple. Cuando el consumidor obtiene elementos de la cola, si el elemento no alcanza el tiempo de retraso, bloquea el hilo actual.
retraso largo = first.getDelay (TimeUtil.nanoseConds); if (demora <= 0) {return Q.Poll; // Bloqueo de cola} else if (líder! = null) {// lider representa un hilo esperando un mensaje de la cola de bloqueo disponible.await (); // Deje que el subproceso ingrese la señal de espera} else {// Cuando el líder sea nulo, establezca el hilo actual en liderazgo de lidera }}}Synchronousqueue
Synchronousqueue es una cola de bloqueo que no almacena elementos. Cada operación de Put debe esperar una operación de toma, de lo contrario, los elementos no se pueden agregar. Synchronousqueue puede considerarse como un pasador, responsable de aprobar datos procesados por el hilo del productor directamente al hilo del consumidor. La cola en sí no almacena ningún elemento, que sea muy adecuado para escenarios transitivos. Por ejemplo, los datos utilizados en un hilo se pasan a otro hilo para su uso. El rendimiento de Synchronousqueue es mayor que el de
Linked Bloquingqueue y ArrayBlokingqueue.
Admite colas de acceso justo. Por defecto, sigue siendo un mecanismo de política injusto
LinkedTransferqueue
LinkedTransferqueue es una cola de transferencia de bloqueo ilimitada compuesta de estructura de lista Linked. En comparación con otras colas de bloqueo, LinkEdTransferqueue tiene más métodos de Trytransfer y Transfer.
método de transferencia
Si un consumidor está esperando actualmente para recibir un elemento (cuando el consumidor usa el método Take () o el método POLL () Limited Limited), el método de transferencia puede transferir inmediatamente los elementos pasados por el productor al consumidor. Si ningún consumidor está esperando el elemento receptor, el método de transferencia almacena el elemento en el nodo de cola de la cola y espera hasta que el consumidor consuma el elemento antes de regresar.
método de trytransfer
Se utiliza para probar si los elementos introducidos por el productor pueden transmitirse directamente al consumidor. Si ningún consumidor está esperando el elemento receptor, se devuelve el falso. La diferencia entre el método de transferencia es que el método TryTransfer regresa inmediatamente, independientemente de si el consumidor lo recibe o no. El método de transferencia debe esperar hasta que el consumidor lo consuma antes de regresar.
Para el método TryTransfer (E E, Tiempo de espera largo, TimeUnit Unit) con límite de tiempo, intenta pasar el elemento aprobado por el productor directamente al consumidor, pero si no hay un consumidor que consuma el elemento, esperará el tiempo especificado antes de regresar. Si el tiempo de espera no ha consumido el elemento, devolverá falso, y si el elemento se consume dentro del tiempo de tiempo de espera, devolverá verdadero.
Bloqueo de LinkedDeque
Linked BloquingDeque es una cola de bloqueo bidireccional compuesta por la estructura de la lista vinculada. La llamada cola de dos vías se refiere al hecho de que puede insertar y eliminar elementos de ambos extremos de la cola. Debido a que la cola de doble extremo tiene una entrada adicional a la cola de operaciones, la competencia se reduce a la mitad cuando múltiples hilos se unen a la cola al mismo tiempo. En comparación con otras colas de bloqueo, Linked BloquingDeque tiene más AddFirst, Addlast, OfferFirst, Offerlast, Peekfirst, Peeklast y otros métodos. El método termina con la primera palabra, indica inserción, adquisición o eliminación del primer elemento de la cola de doble extremo. Un método que termina con la última palabra, lo que indica que el último elemento de la cola de doble extremo se inserta, se obtiene o elimina. Además, el método de inserción ADD es equivalente a Addlast, y el método de eliminación de eliminación es equivalente a eliminar. Sin embargo, el método Take es equivalente a TakeFirst. No sé si es un error en JDK, y es más claro usar el método con el primer y último sufijo al usarlo. La capacidad de la cola se puede inicializar al inicializar el bloqueo vinculado para evitar que se hinchara cuando se vuelva a altar. Además, la cola de bloqueo bidireccional se puede usar en el modo "Robo de trabajo".
Gracias por leer, espero que pueda ayudarte. ¡Gracias por su apoyo para este sitio!