Este artículo habla principalmente de las colecciones involucradas en la concurrencia. Para colecciones ordinarias, consulte [Descripción general de la colección Java]
1. ¿Qué está bloqueando laqueue?
Bloquingqueue es una cola de bloqueo. Desde el bloqueo de la palabra, se puede ver que el acceso a una cola de bloqueo puede causar bloqueo en algunos casos. Hay dos casos bloqueados principales:
1. Cuando la cola esté llena, se enmarará.
2. Cuando la cola esté vacía, estará fuera de la cola.
Por lo tanto, cuando un hilo intenta hacer cola una cola ya completa, se bloqueará a menos que otro hilo realice la operación de la cola; Del mismo modo, cuando un hilo intenta hacer cola una cola vacía, se bloqueará a menos que otro hilo tenga la operación de la cola.
En Java, la interfaz BLOCKINGQUEUE se encuentra en el paquete java.util.concurrent (proporcionado en la versión Java 5). A partir de las características de la cola de bloqueo introducida anteriormente, se puede ver que la cola de bloqueo es segura de hilo.
2. Cómo usar Bloquingqueue
Las colas de bloqueo se utilizan principalmente en escenarios de productores/consumidores. La siguiente imagen muestra una producción de hilo y un escenario de consumo de hilos:
El hilo responsable de la producción crea continuamente objetos nuevos y los inserta en la cola de bloqueo hasta alcanzar el límite superior de esta cola. Después de que la cola alcanza su límite superior, el hilo de producción se bloqueará hasta que el hilo consumido consuma la cola. Del mismo modo, el hilo responsable del consumo consume constantemente objetos de la cola hasta que la cola esté vacía. Cuando la cola está vacía, el hilo de consumo se bloqueará a menos que se inserta un nuevo objeto en la cola.
3. Métodos en la interfaz Bloquingqueue
Hay cuatro conjuntos de métodos para bloquear las colas para realizar insert , remove y examine respectivamente. Cuando las operaciones correspondientes a cada conjunto de métodos no se pueden ejecutar de inmediato, habrá diferentes reacciones. La siguiente tabla enumera estos métodos de manera clasificada:
| - | Lanza la excepción | Valor especial | Bloques | Salir |
|---|---|---|---|---|
| Insertar | Agregar (o) | Oferta (o) | poner (o) | Oferta (o, tiempo de espera, tiempo de tiempo) |
| Eliminar | eliminar (o) | encuesta() | llevar() | Encuesta (tiempo de espera, tiempo de tiempo) |
| Examinar | elemento() | ojeada() |
Las características correspondientes de estos cuatro conjuntos de métodos son:
1. ThrowSexception: si la operación no se puede realizar de inmediato, se lanzará una excepción.
2. Value especial: si la operación no se puede realizar de inmediato, se devolverá un valor especial, generalmente verdadero o falso
3. Bloques: si la operación no se puede realizar de inmediato, la operación se bloqueará
4. TimesOut: si la operación no se puede realizar de inmediato, la operación se bloqueará en el momento especificado. Si no se ejecuta el tiempo especificado, se devolverá un valor especial, que generalmente es verdadero o falso.
Cabe señalar que no podemos insertar null en el bloqueo de Bloquea, de lo contrario se informará NullPointerException .
4. Clase de implementación de Bloquingqueue
Bloquingqueue es solo una interfaz en el paquete java.util.concurrent . Cuando lo usamos específicamente, usamos sus clases de implementación. Por supuesto, estas clases de implementación también se encuentran en el paquete java.util.concurrent . En Java 6, las clases de implementación de Bloquingqueue son principalmente las siguientes:
1. Arrayblokingqueue
2. Delayqueue
3. Linked Bloquingqueue
4. Priority Bockingqueue
5. Synchronousqueue
A continuación presentaremos estas clases de implementación por separado.
4.1 Arrayblokingqueue
ArrayBlockingqueue es una cola de bloqueo limitada, y su implementación interna es una matriz. El significado del límite significa que su capacidad es limitada, debemos especificar su tamaño de capacidad cuando se inicializa y el tamaño de la capacidad no se puede cambiar una vez que se especifique.
ArrayBlockingqueue almacena datos de una manera primero en salida. El objeto recién insertado es la cola y el objeto recién movido es la cabeza. Aquí hay un ejemplo de inicialización y uso de ArrayBlockingqueue:
Bloquingqueue Queue = new ArrayBlockingqueue (1024); queue.put ("1"); objeto de objeto = queue.take ();4.2 Delayqueue
Qué bloqueo de Delayqueue son sus elementos internos. Los elementos en Delayqueue deben implementar la interfaz java.util.concurrent.Delayed . La definición de esta interfaz es muy simple:
La interfaz pública retrasada se extiende comparable <sardado> {Long getDelay (unidad de tiempo de tiempo);} El valor de retorno del método getDelay() es el tiempo de retención antes de que se libere el elemento de cola. Si se devuelve 0 o un负值, significa que el elemento ha expirado y debe ser liberado. En este momento, DeletedQueue liberará este objeto a través de su método take() .
Como se puede ver en la definición de interfaz retrasada anterior, también hereda la interfaz Comparable . Esto se debe a que los elementos en la Cuadría de Deleberada deben clasificarse. En términos generales, ordenamos por prioridad del tiempo de vencimiento del elemento.
Ejemplo 1: especifique un tiempo de vencimiento para un objeto
Primero, definimos un elemento que necesita implementar la interfaz retrasada
La clase pública demora el retraso implementa retrasarse {privado largo vencido; retraso private largo; nombre de cadena privada; DeletEdElement (String ElementName, Long Delay) {this. nombre = elementName; este. retraso = retraso; expirado = (retraso + sistema. CurrentTimemillis ()); } @Override public int Compareto (retrasado o) {demandado en caché = (demandado) o; return cached.getEppired ()> expirado? 1: -1; } @Override public Long getDelay (unidad de tiempo de tiempo) {return (expirado - sistema. CurrentTimemillis ()); } @Override public string toString () {return "DeletedElement [demandado =" + demora + ", name =" + name + "]"; } public Long Long GetEpped () {return expiró; }}Establezca el tiempo de vencimiento de este elemento en 3s
public class DelayqueueeExample {public static void main (string [] args) lanza interruptedException {Delayqueue <LedeDeLement> queue = new Delayqueue <> (); DeletEdElement ELE = New DardeDelement ("Cache 3 segundos", 3000); queue.put (ele); Sistema. out.println (queue.take ()); }}Ejecute esta función principal y podemos encontrar que necesitamos esperar 3 segundos antes de imprimir este objeto.
De hecho, hay muchos escenarios de aplicación para Delayqueue, como conexiones de cierre cronometradas, objetos de caché, procesamiento de tiempo de espera y otros escenarios. Tomemos el examen de los estudiantes como un ejemplo para que todos comprendan el uso de Delayqueue más profundamente.
Ejemplo 2: Trate a todos los estudiantes en el examen como un retraso, quien termina las preguntas primero los publica
Primero, construimos un objeto de estudiante
El estudiante de clase pública implementa runnable, retrasado {nombre de cadena privada; // nombre privado de tiempo de costo largo; // Tiempo para las preguntas de prueba Private Long Time Time; // Tiempo para completar Estudiante público (nombre de cadena, tiempo de costo largo) {esto. nombre = nombre; este. CostoTime = CostoTime; Tiempo terminado = CostTime + Sistema. CurrentTimemillis (); } @Override public void run () {sistema. out.println (nombre + "Enviar el papel, tiempo" + CostTime /1000); } @Override public Long getDelay (unidad de tiempo de tiempo) {return (TimeTime - System. CurrentTimemillis ()); } @Override public int Compareto (retrasado o) {estudiante otro = (estudiante) o; Tiempo de costo de retorno> = otro. tiempo de costo? 1: -1; }}Luego, construya un objeto de maestro para llevar el examen a los estudiantes
maestro de clase pública {static final int stiende_size = 30; public static void main (string [] args) lanza interruptedException {Random r = new Random (); // Piense en todos los estudiantes como una cola de retraso Delayqueue <Student> Students = New DelayQueue <estudiante> (); // Construye un grupo de hilos para permitir que los estudiantes "hagan su tarea" EjecutorService exec = Ejecutors.newFixedThreadPool (student_size); para (int i = 0; i <student_size; i ++) {// Inicializar el nombre y el tiempo del alumno para hacer los estudiantes de prueba. } // Comience la prueba mientras (! Students.isEmpty ()) {Exec.Execute (Students.take ()); } exec.shutdown (); }}Echemos un vistazo a los resultados de la ejecución:
Estudiante 2 Enviar el documento, 3
Estudiante 1 entrega en papeles, tomando 5
Estudiante 5 Enviar el documento, 7
Estudiante 4 Envíe el documento, tomando 8
Estudiante 3 Envíe el documento, 11
A través de los resultados de ejecución, podemos encontrar que cada estudiante "enviará el documento" después de que llegue la hora de inicio especificada ( dependiendo del método getDelay () ), y el documento se enviará primero ( dependiendo del método Compareto () ).
Al observar su código fuente, puede ver que la implementación interna de Delayqueue usa priorityqueue y un bloqueo:
4.3 Bloqueque Linkedqueue
La configuración del tamaño de la cola de bloqueo de Blokingue Linked es opcional. Si especificamos un tamaño al inicializar, está limitado y, si no se especifica, está limitado. Se dice que es ilimitado, pero de hecho, el tamaño predeterminado es Integer.MAX_VALUE Capacidad. Su implementación interna es una lista vinculada.
Al igual que ArrayBlockingqueue, Linked Blokingqueue también almacena datos de una manera de primera vez. El objeto recién insertado es la cola y el objeto recién movido es la cabeza. Aquí hay un ejemplo de inicialización y fabricación de LinkedBlokingqueue:
BLOCKINGQUEUE <String> Unbounded = new LinkedBlowingqueue <String> (); Bloquingqueue <String> Bounded = New LinkedBlowingqueue <String> (1024); Bounded.put ("Value"); String value = Bounded.take ();4.4 Priority Bockingqueue
PriorityBlokingqueue es una cola sin límites, y sus reglas de clasificación son las mismas que java.util.PriorityQueue . Cabe señalar que los objetos nulos se permiten insertar en priorityblockingqueue.
Todos los objetos insertados en PriorityBlockqueue deben implementar la interfaz java.lang.Comparable , y las reglas de clasificación de prioridad de la cola se definen de acuerdo con nuestra implementación de esta interfaz.
Además, podemos obtener un iterador de PriorityBlockingqueue, pero este iterador no garantiza la iteración en orden de prioridad.
Demos un ejemplo para ilustrar. Primero, definimos un tipo de objeto, que necesita implementar la interfaz comparable:
Public Class PriorityElement implementa comparable <riorityElement> {private int priority; // Definir prioridad priorityElement (int priority) {// inicializar prioridad this.priority = priority;}@overridePublic int comparto (priorityElement O) {// Ordena por tamaño de prioridad prioridad> = o.getpriority ()? 1: -1;} public int getPriority () {return priority;} public void setPriority (int priority) {this.priority = priority;}@overridePublic string toString () {return "priorityElement [priority =" + priority + "]";}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}Luego establecemos al azar la prioridad de la cola
Public Class PriorityBlokingqueueExample {public static void main (string [] args) lanza interruptedException {priorityBlockingqueue <riorityElement> queue = new PriorityBlockingqueue <> (); for (int i = 0; i <5; i ++) {random random = new Random (); PriorityElement ELE = New PriorityElement (Random.NextInt (10)); queue.put (ele); } while (! queue.isEmpty ()) {system.out.println (queue.take ()); }}}Consulte los resultados de ejecución:
PriorityElement [prioridad = 3]
PriorityElement [prioridad = 4]
PriorityElement [prioridad = 5]
PriorityElement [prioridad = 8]
PriorityElement [prioridad = 9]
4.5 Synchronousqueue
Solo se permite un elemento dentro de la cola Synchronousqueue. Cuando un hilo inserta un elemento, se bloqueará a menos que el elemento sea consumido por otro hilo.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.