JavaRush /Blog Java /Random-ES /Ejemplo de SynchronousQueue en Java: resolución del probl...
profeg
Nivel 18

Ejemplo de SynchronousQueue en Java: resolución del problema Productor Consumidor

Publicado en el grupo Random-ES
Ejemplo de SynchronousQueue en Java: resolución del problema Productor Consumidor
SynchronousQueue es un tipo especial de BlockingQueue en el que cada operación de inserción debe esperar un comando de eliminación correspondiente en otro hilo, y viceversa. Cuando llamas al método put() en un SynchronousQueue, se bloquea hasta que otro hilo le quita ese elemento. En consecuencia, si otro hilo intenta eliminar un elemento y el elemento no está allí, ese hilo se bloquea hasta que el otro hilo pone el elemento en la cola. Puedes pensar en SynchronousQueue como un atleta ( hilo ) corriendo con la antorcha olímpica, corre con la antorcha (el objeto que se pasa) y se la pasa a otro atleta que espera al otro lado. Si presta atención al nombre, comprenderá que SynchronousQueue se llama así por una razón: transfiere datos sincrónicamente a otro hilo ; espera a que alguien recoja los datos en lugar de simplemente introducirlos y salir (una operación asincrónica). Si está familiarizado con CSP y Ada, entonces sabrá que las colas sincronizadas son similares a la reunión de subprocesos. Son muy adecuados para construcciones de transferencia de control en las que un objeto que se ejecuta en un subproceso debe sincronizarse con un objeto en otro subproceso para poder pasarle alguna información, evento o tarea. En tutoriales de programación multiproceso anteriores, aprendimos cómo resolver el problema productor-consumidor utilizando los métodos esperar y notificar y BlockingQueue . Ahora aprenderemos cómo aplicar el patrón productor-consumidor usando SynchronousQueue. Esta clase además admite un comportamiento justo para ordenar las esperas de los subprocesos del productor y del consumidor. Por defecto, este pedido no está garantizado. Sin embargo, las colas creadas con propiedades justas garantizan el acceso de los subprocesos en una cola FIFO (Primeros en entrar, primero en salir).
Productor/Consumidor usando SynchronousQueue en Java.
Ejemplo de SynchronousQueue en Java: resolución del problema Productor Consumidor - 1 Como dije anteriormente, no hay nada mejor que el problema productor-consumidor para comprender la comunicación entre subprocesos en cualquier lenguaje de programación. En este problema, un hilo actúa como productor que produce eventos y tareas, y el otro hilo actúa como consumidor del mismo. Se utiliza un búfer compartido para transferir datos del productor al consumidor. La dificultad de solucionar este problema llega en casos extremos, por ejemplo, cuando el fabricante se ve obligado a esperar porque... el buffer está lleno o el consumidor se ve obligado a esperar porque el búfer está vacío. Esto se solucionó fácilmente, porque... La cola de bloqueo proporcionó no solo un búfer para almacenar datos, sino también control de flujo, bloqueando el hilo que llama al método put() (Productor) si el búfer estaba lleno, y bloqueando el hilo que llama al método take() (Consumidor) si el el buffer estaba vacío. Ahora resolveremos este mismo problema usando SynchronousQueue, un tipo especial de colecciones paralelas con capacidad cero. En el siguiente ejemplo, tenemos dos hilos llamados PRODUCTOR y CONSUMIDOR (siempre dé nombres a los hilos, este es un muy buen estilo de programación multiproceso), el primer hilo publica la puntuación en el juego y el segundo hilo lo consume. La puntuación del juego no es más que un objeto de tipo String. Pero si ejecuta el programa con un tipo diferente, no notará ninguna diferencia. Para comprender cómo funciona SynchronousQueue y cómo resolver el problema productor-consumidor, debe: ejecutar el programa de depuración en el entorno Eclipse o simplemente iniciar el hilo del productor comentando consumer.start(); si el hilo del consumidor no se está ejecutando, el hilo del productor se bloqueará en queue.put(event); si se está ejecutando, no podrá ver al productor [PRODUCER] publicando el evento :FOUR. Esto sucede porque comportamiento específico de SynchronousQueue, que garantiza que el hilo que publica datos se bloqueará hasta que otro hilo tome los datos, y viceversa. Puedes probar el resto del código comentando productor.start(); e iniciando solo el hilo del consumidor. Si estudia detenidamente lo que genera el programa, notará que el orden de salida se invierte. Parece que el hilo [CONSUMIDOR] tomó los datos antes de que el hilo [PRODUCTOR] los produjera. Esto se debe a que SynchronousQueue no garantiza la puesta en cola de forma predeterminada. Pero tiene reglas de equidad que establecen el acceso a los subprocesos en orden FIFO. Puede habilitar estas reglas pasando true al constructor SynchronousQueue sobrecargado de esta manera: import java.util.concurrent.SynchronousQueue; /** * Java Program to solve Producer Consumer problem using SynchronousQueue. A * call to put() will block until there is a corresponding thread to take() that * element. * * @author Javin Paul */ public class SynchronousQueueDemo{ public static void main(String args[]) { final SynchronousQueue queue = new SynchronousQueue (); Thread producer = new Thread("PRODUCER") { public void run() { String event = "FOUR"; try { queue.put(event); // thread will block here System.out.printf("[%s] published event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; producer.start(); // starting publisher thread Thread consumer = new Thread("CONSUMER") { public void run() { try { String event = queue.take(); // thread will block here System.out.printf("[%s] consumed event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; consumer.start(); // starting consumer thread } } Output: [CONSUMER] consumed event : FOUR [PRODUCER] published event : FOUR new SynchronousQueue(boolean fair).
Lo que necesita recordar sobre SynchronousQueue en Java.

A continuación se muestran algunas propiedades importantes de este tipo especial de cola de bloqueo en Java. Es muy útil pasar datos de un hilo a otro de forma sincronizada. Esta cola no tiene capacidad y está bloqueada hasta que otro hilo la libere.

  1. SynchronousQueue se bloquea y, hasta que un hilo esté listo para tomar datos, otro intentará colocar datos.
  2. SynchronousQueue no tiene volumen. Es decir, no contiene datos.
  3. SynchronousQueue se utiliza para implementar una estrategia de cola directa, donde un subproceso pasa el control a un subproceso en espera o crea uno nuevo si está permitido; de lo contrario, el control no se transfiere.
  4. Esta cola no permite datos nulos. Un intento de agregar un elemento nulo generará una NullPointerException .
  5. Si utiliza otros métodos de Collection (como contiene), SynchronousQueue se comporta como una colección vacía.
  6. No puedes usar el método peek de SynchronousQueue porque el elemento solo existe cuando intentas eliminarlo; Además, no podrá insertar elementos (usando ningún método) hasta que otro hilo intente eliminarlos.
  7. No podrás usar el iterador para SynchronousQueue porque... no tiene elementos.
  8. SynchronousQueue se puede crear con reglas justas donde el acceso a los subprocesos está garantizado en orden FIFO.
Quizás se trate de SynchronousQueue en Java. Analizamos algunas de las características especiales de esta colección de subprocesos múltiples y aprendimos cómo resolver el clásico problema productor-consumidor usando SynchronousQueue en Java. Por cierto, llamarlo Cola no es del todo correcto, porque... no contiene elementos. La llamada a put() no se completará hasta que otro hilo llame a take(). Es más correcto pensar en ello como un lugar de encuentro de hilos, donde comparten un objeto. En otras palabras, es una utilidad para el paso sincronizado de objetos en Java, quizás una alternativa más segura al método de esperar y notificar .
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION