Red de conocimiento de abogados - Derecho de sociedades - Cooperación de sincronización de subprocesos de cola de bloqueo de Java

Cooperación de sincronización de subprocesos de cola de bloqueo de Java

La interfaz Queue y el conjunto de listas heredan la interfaz Collection en el mismo nivel. LinkedList implementa la interfaz Queue. La interfaz Queue limita los derechos de acceso a los métodos LinkedList (es decir, si el tipo de parámetro en el método). es Queue, solo puede acceder a los métodos definidos por la interfaz de cola y no puede acceder directamente a los métodos que no son de cola de LinkedList), por lo que solo los métodos apropiados pueden usar BlockingQueue, que hereda la interfaz de cola

Queue es una estructura de datos. Tiene dos operaciones básicas: agregar un elemento al final de la cola y eliminar un elemento del encabezado de la cola. Esto significa que la cola administra los datos primero en entrar, primero en salir. elemento a una cola de bloqueo que ya está llena, o eliminar un elemento de una cola de bloqueo vacía hará que el hilo se bloquee. Las colas de bloqueo son una herramienta útil cuando varios subprocesos cooperan. Los subprocesos de trabajo pueden almacenar periódicamente resultados intermedios en la cola de bloqueo mientras que otros subprocesos de trabajo extraen los resultados intermedios y los modifican en el futuro. La cola equilibrará automáticamente la carga si el primero. un conjunto de subprocesos se ejecuta más lento que el segundo, el segundo conjunto de subprocesos se bloqueará mientras espera el resultado. Si el primer conjunto de subprocesos se ejecuta más rápido, esperará a que el segundo conjunto de subprocesos se ponga al día. La siguiente tabla muestra la cola de bloqueo de jdk. operaciones

Agregar agrega un elemento y arroja una excepción IIIegaISlabEepeplian si la cola está llena

¿eliminar? Elimina y devuelve el elemento al principio de la cola y lo arroja si la cola está vacía. ¿Lanzar un elemento NoSuchElementException

? Devolver el elemento al principio de la cola. Si la cola está vacía, lanzar una oferta NoSuchElementException

. y devuelve verdadero? Devuelve falso si la cola está llena

encuesta Elimina y devuelve el elemento al principio de la cola Devuelve nulo si la cola está vacía

Devuelve el elemento en? el encabezado de la cola si Si la cola está vacía, devuelve nulo

Poner ¿Agregar un elemento? ¿Bloquear si la cola está llena

Toma Eliminar y devuelve el elemento al comienzo de la cola? cola Bloquear si la cola está vacía

Eliminar elemento oferta encuesta peek en realidad pertenece a la interfaz de cola

Las operaciones de bloqueo de colas se pueden dividir en las siguientes tres categorías según sus métodos de respuesta Las operaciones de eliminación y elemento se utilizan cuando se intenta agregar a una cola llena. Se genera una excepción cuando se recupera un elemento de una cola vacía. Por supuesto, en un programa de subprocesos múltiples, la cola puede llenarse o vaciarse en cualquier momento. , por lo que es posible que desee utilizar el método de encuesta de oferta. Estos métodos simplemente muestran un mensaje de error.

Tenga en cuenta que los métodos de encuesta y visualización devuelven un valor nulo cuando se produce un error. Es ilegal insertar un valor nulo en la cola.

También hay variantes de método de oferta y encuesta con tiempo de espera, como la siguiente llamada

boolean Success = q oferta (x TimeUnit MILLISECONDS. );

Intente insertar un elemento al final de la cola en milisegundos. Si tiene éxito, devuelva verdadero inmediatamente; de ​​lo contrario, cuando se alcance el tiempo de espera, devuelva falso y llame al mismo método.

Object head = q poll(TimeUnit MILLISECONDS);

Si el elemento principal de la cola se elimina con éxito en milisegundos, el elemento principal se devolverá inmediatamente; de ​​lo contrario, se devolverá después de que se alcance el tiempo de espera. de vez en cuando

Finalmente, tenemos las operaciones de bloqueo put y take. El método put bloquea el método take cuando la cola está llena.

Bloqueo cuando la cola está vacía

El paquete ncurrent proporciona una variante de la cola de bloqueo. De forma predeterminada, la capacidad de LinkedBlockingQueue no tiene límite superior (no es exacto. La capacidad es Entero MAX_VALUE cuando no se especifica). De lo contrario, al poner ¿Cómo se puede bloquear?) Pero también puede optar por especificar su capacidad máxima. Es una cola basada en una lista vinculada. Esta cola clasifica los elementos por FIFO (primero en entrar, primero en salir). p> ArrayBlockingQueue necesita especificar la capacidad al construir y puede elegir si debe ser justo. Si el parámetro de equidad se establece en verdadero, el hilo con el tiempo de espera más largo se procesará primero (de hecho, esta equidad se logra configurando). ReentrantLock es verdadero, es decir, el hilo con el tiempo de espera más largo funcionará primero). Por lo general, la equidad le hará pagar un precio en rendimiento y usarlo solo cuando realmente lo necesite. Es una cola circular de bloqueo basada en matrices. la cola clasifica los elementos según el principio FIFO (primero en entrar, primero en salir).

PriorityBlockingQueue es un bloque de prioridad La cola no es la cola de primero en entrar, primero en salir. Los elementos se eliminan en orden de prioridad. La cola no tiene límite superior (mirando el código fuente). PriorityBlockingQueue es un reempaquetado de PriorityQueue y se basa en la estructura de datos del montón. PriorityQueue no tiene límite de capacidad, al igual que ArrayList, por lo que no se colocará en la cola de bloqueo prioritario. bloqueado Aunque esta cola es lógicamente ilimitada, intentar realizar una operación de adición puede causar un OutOfMemoryError debido al agotamiento de los recursos. Sin embargo, si la cola está vacía, la operación de toma de elementos se bloqueará. Además, los elementos que ingresan a la cola deben tener capacidades de comparación.

Finalmente, DelayQueue (implementado en base a PriorityQueue) es una cola de bloqueo ilimitada que almacena elementos retrasados ​​​​solo durante el período de retraso. cuando está lleno, el encabezado de la cola es el elemento retrasado que tiene el tiempo de almacenamiento más largo después de que expire el retraso. Si el retraso no ha expirado, la cola no tiene encabezado y la encuesta devolverá nulo cuando getDelay(TimeUnit NANOSECONDS). ) método de un elemento Cuando se devuelve un valor menor o igual a cero, se produce una encuesta de caducidad y el elemento se puede eliminar. Esta cola no permite el uso de elementos nulos. A continuación se muestra la interfaz retrasada. >Código Java

interfaz pública Retrasado extiende Comparable {

long getDelay(TimeUnit unit

}

interfaz pública; Retrasado extiende Comparable {

Long getDelay(TimeUnit unit);

}

Los elementos colocados en DelayQueue también implementarán el método pareTo. esto para ordenar los elementos.

El siguiente ejemplo muestra cómo usar la cola de bloqueo para controlar el conjunto de subprocesos. El programa busca todos los archivos en un directorio y todos sus subdirectorios e imprime una lista de los archivos que contienen. la palabra clave especificada. Como se puede ver en el siguiente ejemplo, dos beneficios importantes de usar la cola de bloqueo son los subprocesos múltiples. No se requiere sincronización adicional cuando se operan diferentes colas. Además, la cola equilibrará automáticamente la carga. si el procesamiento en ambos lados (producción y consumo) es rápido, se bloqueará, reduciendo así la brecha de velocidad de procesamiento entre los dos lados. La siguiente es la implementación específica

Código Java

.

clase pública BlockingQueueTest {

voi público estático

d main(String[] args) {

Entrada del escáner = nuevo Escáner(Entrada del sistema

Salida del sistema print( Ingrese el directorio base (por ejemplo, /usr/local/jdk /src) ): );

Directorio de cadenas = en nextLine();

Salida del sistema (Ingrese la palabra clave (por ejemplo, volátil):

Palabra clave de cadena = en); nextLine();

final int FILE_QUEUE_SIZE = ;//Tamaño de la cola de bloqueo

final int SEARCH_THREADS = ;//Número de hilos de búsqueda de palabras clave

// Bloqueo cola basada en ArrayBlockingQueue

BlockingQueue queue = new ArrayBlockingQueue(

FILE_QUEUE_SIZE

// Inicia solo un hilo para buscar en el directorio;

Enumerador FileEnumerationTask = new FileEnumerationTask(cola

nuevo archivo(directorio));

nuevo hilo(enumerador) inicio(); > //Iniciar un hilo para buscar la palabra clave especificada en el archivo

for (int i = ; i <= SEARCH_THREADS; i++)

new Thread(new SearchTask(cola palabra clave )) start();

 }

 }

 class FileEnumerationTask implementa Runnable {

 //El objeto de archivo ficticio se coloca en La cola de bloqueo finalmente se usa para indicar que el archivo ha sido atravesado

public static File DUMMY = new File()

private BlockingQueue cola; p>directorio inicial de archivo privado;

tarea de enumeración de archivos pública (BlockingQueue directorio inicial de archivo) {

esta cola = cola

este directorio inicial = directorio inicial <; /p>

}

public void run() {

intenta {

enumerar(startingDirectory

poner cola); (DUMMY) ;// La ejecución aquí indica que los archivos en el directorio especificado han sido atravesados

} catch (InterruptedException e) {

}

}

//Coloca todos los archivos en el directorio especificado en la cola de bloqueo en forma de objetos de archivo

public void enumerate(directorio de archivos) lanza InterruptedException {

Archivo[] archivos = directorio listFiles()

for (Archivo archivo: archivos) {

 if (file isDirectory())

enumerate(file);

else

//Coloca el elemento al final de la cola y bloquea si la cola está llena

cola put(file);

}

}

}

clase SearchTask; implementa Runnable {

p>

cola BlockingQueue privada

palabra clave de cadena privada

task de búsqueda pública (cola BlockingQueue palabra clave; ) {

esta cola = cola

esta palabra clave = palabra clave

}

public void run() {

>

try {

boolean done = false;

while (!done) {

//Obtiene el primer elemento de la cola y bloquea si la cola está vacía

Archivo file = queue take();

if (file == FileEnumerationTask DUMMY) {

//Sácalo y ponlo. nuevamente para que otros hilos puedan terminarlo rápidamente cuando lo lean

queue put(file

done = true

} else

buscar(archivo);

}

} catch (IOException e) {

e printStackTrace(); } catch (InterruptedException e) {

}

}

la búsqueda pública vacía (archivo) lanza IOException {

Escáner en = nuevo escáner (nuevo FileInputStream (archivo));

int número de línea =

mientras (en hasNextLine()) {

número de línea++; p>String line = in nextLine();

 if (ntains(palabra clave))

Sistema fuera printf( %s:%d:%s%n file getPath() lineNumber

línea);

 }

en cerrar();

} lishixinzhi/Article/program/Java/hx/201311/ 26657