1. ¿Qué es una cola de bloqueo?
Una cola es una estructura de datos que tiene dos operaciones básicas: agregar un elemento al final de la cola y eliminar un elemento de la cabeza de la cola. La diferencia entre los equipos de bloqueo y las colas ordinarias es que las colas ordinarias no bloquearán el hilo actual. Cuando se enfrentan a modelos similares al productor del consumidor, se deben implementar estrategias de sincronización adicionales y estrategias de atención entre subpuestas. El uso de una cola de bloqueo bloqueará el hilo actual. Cuando la cola está vacía, se bloqueará la operación de obtener elementos de la cola. Cuando la cola está llena, la operación de agregar elementos a la cola también se bloqueará.
2. La cola de bloqueo principal y sus métodos
El paquete java.util.concurrent proporciona varias colas de bloqueo principal, principalmente como sigue:
1) ArrayBlockingqueue: una cola de bloqueo basada en la implementación de la matriz. Al crear un objeto ArrayBlockingqueue, su capacidad debe especificarse. También se puede especificar para las políticas de acceso. Por defecto, no es justo, es decir, no garantiza que el hilo con el tiempo de espera más largo pueda acceder primero a la cola.
2) Linked Bloquingqueue: una cola de bloqueo basada en una lista vinculada. Si el tamaño de la capacidad no se especifica al crear un objeto LinkedBlockingqueue, el tamaño predeterminado es entero.max_value.
3) Las dos colas anteriores son las colas en primer lugar, pero PriorityBockingqueue no lo es. Ordenará los elementos de acuerdo con la prioridad de los elementos y el dequiro en orden de prioridad. Cada elemento Dequeue es el elemento de mayor prioridad. Tenga en cuenta que esta cola de bloqueo es una cola de bloqueo ilimitada, es decir, no hay límite superior en la capacidad (puede saber a través del código fuente que no tiene un indicador de señal lleno del contenedor). Los dos primeros tipos son colas limitadas.
4) Delayqueue: Basado en Priorityqueue, una cola de bloqueo de retraso. El elemento en el Delayqueue solo puede obtener el elemento de la cola cuando ha alcanzado el tiempo de retraso especificado. Delayqueue también es una cola ilimitada, por lo que la operación (productor) de insertar datos en la cola nunca se bloqueará, y solo se bloqueará la operación (consumidor) de obtener datos.
Las colas de bloqueo incluyen la mayoría de los métodos en colas sin bloqueo y proporcionan varios otros métodos muy útiles:
El método PUT se usa para almacenar elementos en la cola de la cola, y si la cola está llena, espera;
El método Take se usa para obtener elementos de la cola, y si la cola está vacía, espere;
El método de oferta se utiliza para almacenar elementos en la cola de la cola. Si la cola está llena, esperará por un tiempo determinado. Cuando se alcanza el período de tiempo, si la inserción no ha tenido éxito, devolverá falso; De lo contrario, devolverá verdadero;
El método de la encuesta se utiliza para obtener elementos de la primera cola. Si la cola está vacía, esperará por un tiempo determinado. Cuando se alcanza el período de tiempo, si se recupera, volverá nulo; De lo contrario, devolverá el elemento obtenido;
Aquí hay un código:
import java.util.concurrent.arrayblockingqueue;/** * @author autor: xu jiane-mail: [email protected] * @version creado: 20 de marzo de 2016 a las 12:52:53 pm * Descripción de la clase */Bloque de clase pública {public static void Main (String [] args) lanza Interrupted Exception { java.util.concurrent.blockingqueue <tring> bloquequeue = new ArrayBlockingqueue <> (5); para (int i = 0; i <10; i ++) {// Agregue el elemento especificado a esta cola Bloquingqueue.put ("Agregar elemento"+i); System.out.println ("Se agregó elemento a la cola de bloqueo:" + i); } System.out.println ("El programa termina esta vez y saldrá ----"); }}
Cuando el número de colas de bloqueo de límite es 5, después de agregar 5 elementos, el proceso se bloqueará fuera de la cola y espera, y el programa no termina en este momento.
Cuando la cola está llena, eliminamos el elemento de encabezado y podemos continuar agregando elementos a la cola de bloqueo. El código es el siguiente:
Public Class Bloquingqueue {public static void main (string [] args) lanza interruptedException {java.util.concurrent.blockingqueue <string> bloquequeue = new ArrayBlowingqueue <> (5); para (int i = 0; i <10; i ++) {// Agregue el elemento especificado a esta cola Bloquingqueue.put ("Agregar elemento"+i); System.out.println ("Se agregó elemento a la cola de bloqueo:" + i); if (i> = 4) System.out.println ("Retire el elemento de encabezado" +Bloquingqueue.take ()); } System.out.println ("El programa termina esta vez y saldrá ----"); }Los resultados de la ejecución son los siguientes:
3. Principio de implementación de la cola de bloqueo <Br /> El siguiente analiza principalmente el principio de implementación de ArrayBlockingqueue.
Primero, echemos un vistazo a las variables miembros de la clase ArrayBlockingqueue:
Public Class ArrayBlockingqueue <E> extiende AbstractQueue <E> implementa Bloqueque de Bloquea <E>, Java.io.Serializable { / ** Structure Structure-Array* / final de la matriz final []; / ** Subíndico de elemento de cabeza de equipo*/ int TakeIndex; / ** Subíndico del elemento de cola del equipo*/ int putIndex; / ** Número total de elementos de cola*/ int Count; / ** Reentrantlock*/ Final Reentrantlock Lock; / ** CONDICIÓN DE HABITA NOTACIÓN*/ Condición final privada no notable; / ** Condición de espera notable*/ Condición final privada Notfull; /** * Estado compartido para iteradores actualmente activos, o NULL si se sabe que no hay ninguno. Permite que las operaciones de cola actualicen * Estado de iterador. */ transitorio ITRS ITRS = NULL;Como puede ver, el arrayblockingqueue utilizado para almacenar elementos es en realidad una matriz.
Echemos un vistazo a la implementación de dos métodos importantes de ArrayBlockingqueue, PUT () y Take ()::
public void put (e e) lanza interruptedException {// verifique primero si E es vacío checkNotnull (e); // adquirir el bloqueo final de reentrantlock Lock = this.lock; LOCK.LockInterruption (); Pruebe {// Cuando la cola esté llena, ingrese la condición y espere mientras (count == items.length) notfull.await (); // La cola no está satisfecha, realiza la operación de cola enqueue (e); } Finalmente {// libera el bloqueo bloque.unlock (); }} Veamos la operación de unión específica:
Private void enqueue (e x) {objeto final [] elementos = this.items; // ítems de Enterminación [putIndex] = x; if (++ putIndex == items.length) putIndex = 0; // número total de colas +1 recuento ++; // Seleccione un hilo al azar en el conjunto de espera de la condición notable para desbloquear su estado de bloqueo Notempty.signal (); } Aquí está el código fuente del método Take ():
public E Take () lanza interruptedException {// adquirir el bloqueo final de reentrantlock bloqueo = this.lock; LOCK.LockInterruption (); Pruebe {// La cola está vacía mientras (count == 0) // el hilo se une a la condición notable que espera el set noTempty.aWait (); // no vacío, salga de la cola return dequeue (); } Finalmente {// libera el bloqueo bloque.unlock (); }} 4. Aplicación de colas de bloqueo: implementación del modelo de productor de consumidor
/** * @Author Autor: Xu Jiane-Mail: [email protected] * @Version Tiempo creado: 20 de marzo de 2016 a las 2:21:55 pm * Descripción de la clase: Modo del productor de consumidor implementado mediante la cola */Prueba de clase pública {Private INT Queuesize = 10; privado arrayblockingqueue <integer> queue = new ArrayBlockingqueue <Integer> (queuesize); public static void main (string [] args) {test test = new test (); Productor productor = test.new productor (); Consumer Consumer = test.new Consumer (); productor.start (); Consumer.Start (); } Class Consumer extiende el hilo {@Override public void run () {consumo (); } consumo vacío privado () {while (true) {try {queue.take (); System.out.println ("Tome un elemento de la cola, y la cola permanece" + queue.size () + "Elements"); } catch (InterruptedException e) {E.PrintStackTrace (); }}}}} El productor de clase extiende el hilo {@Override public void run () {product (); } private void product () {while (true) {try {queue.put (1); System.out.println ("Inserte un elemento en la cola, el espacio restante en la cola:"+ (queuesize - queue.size ())); } catch (InterruptedException e) {E.PrintStackTrace (); }}}}}}
Lo anterior se trata de este artículo, espero que sea útil para el aprendizaje de todos.