2010-07-22 35 views
8

Considere un BlockingQueue y algunos hilos esperando en poll(long, TimeUnit) (posiblemente también en take()).Cómo liberar inmediatamente los hilos que esperan en un BlockingQueue

Ahora la cola está vacía y se desea notificar a los hilos de espera que pueden dejar de esperar. El comportamiento esperado es tener null devuelto o el InterruptedException declarado arrojado.

Object.notify() no funcionará para LinkedBlockingQueue ya que los hilos están esperando en un bloqueo interno.

¿Alguna manera directa?

+0

¿Por qué harías eso? Depende de BlockingQueue decidir qué cadena de invocación se puede reanudar.En función de la implementación de BlockingQueue, no hay una suposición confiable posible en el estado de la cola. – cafebabe

+1

@bfoo, supongo que el objetivo es terminar los hilos con elegancia cuando ya no hay más trabajo por hacer. –

Respuesta

5

La manera convencional es interrumpir los hilos, pero esto por supuesto requiere que manejen las interrupciones correctamente.

Esto significa atrapar y manejar correctamente InterruptedException s alrededor de los métodos de bloqueo, y para verificar (y actuar sobre) la bandera interrupted regularmente de lo contrario.

No hay nada en la especificación API o el idioma que une a la interrupción de cualquier semántica de cancelaciones, pero en la práctica, el uso de interrupción para otra cosa que la cancelación es frágil y difícil de sostener en aplicaciones más grandes. [...]

La interrupción es generalmente la forma más sensata de implementar la cancelación.

Dice Java Concurrency in Practice en la sección 7.1.1. Un ejemplo de manipulación de interrupción correctamente, de mismo (este es un hilo productor, no un consumidor, pero que la diferencia es insignificante en el contexto actual):

class PrimeProducer extends Thread { 
    private final BlockingQueue<BigInteger> queue; 

    PrimeProducer(BlockingQueue<BigInteger> queue) { 
     this.queue = queue; 
    } 

    public void run() { 
     try { 
      BigInteger p = BigInteger.ONE; 
      while (!Thread.currentThread().isInterrupted()) 
       queue.put(p = p.nextProbablePrime()); 
     } catch (InterruptedException consumed) { 
      /* Allow thread to exit */ 
     } 
    } 
    public void cancel() { interrupt(); } 
} 

Una solución alternativa sería la de establecer el parámetro de tiempo de espera de poll razonablemente bajo, de modo que el hilo se despierta regularmente y puede notar interrupciones lo suficientemente rápido. Aún así, creo que siempre es una buena práctica manejar InterruptedException explícitamente de acuerdo con su política específica de cancelación de subprocesos.

+0

Excepto que parece que poll() no responde a la interrupción. –

1

Yo diría que hay algo mal con su diseño. Los hilos que consumen fuera de un BlockingQueue no deberían necesitar ser interrumpidos de tal manera. Si deben hacer otra cosa en un intervalo regular (como comprobar el estado de una variable) mientras consumen también de la cola, entonces debe usar el método poll() con un tiempo de espera configurado de forma tal que las dos acciones se puedan intercalar.

13

Javadoc para la BlockingQueue sugiere una buena manera:

Un BlockingQueue hace que no sean intrínsecamente apoyo de cualquier tipo de "cerrar" o la operación "apagado" para indicar que se añadirán ningún producto más. Las necesidades y el uso de tales características tienden a ser dependientes de la implementación. Por ejemplo, una táctica común es que los productores inserten objetos especiales al final de la corriente o veneno , que se interpretan como cuando los toman los consumidores.

+9

Buena idea: como porteadores en un gran aeropuerto internacional, solíamos colocar una caja blanca vacía en la cinta transportadora para indicarle al porteador del lado receptor que no saldrían más bolsas de ese vuelo; esa caja blanca es exactamente lo que llamar veneno. –

Cuestiones relacionadas