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.
¿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
@bfoo, supongo que el objetivo es terminar los hilos con elegancia cuando ya no hay más trabajo por hacer. –