package ar.com.javacuriosities.concurrency.blocking_queue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /* * Interface BlockingQueue * * Sus métodos tienen 4 posibles formas de tratar las operaciones que no pueden ser atendidas inmediatamente * pero si posiblemente en el futuro. * * 1- Lanzar una excepción * 2- Devolver un valor null o false dependiendo de la operación * 3- Bloquear el thread actual indefinidamente hasta que se pueda realizar la operación. * 4- Bloquear durante un tiempo máximo dado. * * Throws exception - Special value - Blocks - Times out * Insert add(e) offer(e) put(e) offer(e, time, unit) * Remove remove() poll() take() poll(time, unit) * Examine element() peek() - - * * BlockingQueue no acepta valores nulos. * * Puede tener una capacidad limitada. Si no se le indica nada su capacidad será Integer.MAX_VALUE. * * BlockingQueue está diseñada para actuar como una cola "Productor/Consumidor" (Insertar/Leer) más que como una Collection y aunque dispone * de método como remove(x), no funcionan de forma muy eficiente y es mejor no usarlo mucho de esa manera. * * BlockingQueue es thread-safe, todos sus métodos de gestión de colas (no así lo típicos de una Collection) están preparados para la concurrencia. * * BlockingQueue no tiene un método de Close o shutdown para indicar que no se añadirán más items. * * Una forma común de hacer esto sería que los Productor insertasen una clave de fin * que los Consumidor supieran interpretar. * * Implementaciones: * LinkedBlockingQueue —> Implementación con nodos conectados y limite opcional * ArrayBlockingQueue —> Implementación en la cual debemos especificar el limite * PriorityBlockingQueue —> Implementación donde la prioridad esta dada por el resultado de comparación, los objetos deben ser comparables * DelayQueue —> Implementación en la cual los elementos están disponible después de cierto tiempo * SynchronousQueue —> Implementación similar rendezvous (Término de origen francés, Significado encuentro o cita), el tamaño es 0 y solo elemento esta disponible de un thread cuando otro lo remueve */ public class Main { public static void main(String[] args) { // Creamos una queue BlockingQueue<Integer> sharedQueue = new LinkedBlockingQueue<Integer>(); // Creamos el Producer & Consumer Thread producer = new Thread(new Producer(sharedQueue)); Thread consumer = new Thread(new Consumer(sharedQueue)); // Ejecutamos los threads producer.start(); consumer.start(); } /* * Representa al Productor que genera datos y los inserta en la queue */ private static final class Producer implements Runnable { private final BlockingQueue<Integer> sharedQueue; public Producer(BlockingQueue<Integer> sharedQueue) { this.sharedQueue = sharedQueue; } @Override public void run() { try { for (int i = 0; i < 10; i++) { System.out.println("Producer generating element number: " + i); sharedQueue.put(i); } sharedQueue.put(-1); } catch (InterruptedException e) { // Log and Handle exception e.printStackTrace(); } } } /* * Clase que representa un consumidor que consume desde la queue */ private static final class Consumer implements Runnable { private final BlockingQueue<Integer> sharedQueue; public Consumer(BlockingQueue<Integer> sharedQueue) { this.sharedQueue = sharedQueue; } @Override public void run() { int valor; boolean seguir = true; while (seguir) { try { valor = (Integer) sharedQueue.take(); if (valor == -1) { seguir = false; continue; } System.out.println("Consumer picked: " + valor); } catch (InterruptedException e) { // Log and Handle exception e.printStackTrace(); } } } } }