2012-05-01 8 views
16

He heredado recientemente una aplicación Java grande que casi no tiene seguridad de subprocesos. En lo que estoy trabajando actualmente es en conseguir que todos los subprocesos manejen correctamente la interrupción en lugar de usar el muy malo Thread.stop().Métodos que borran el indicador Thread.interrupt()

Parte del problema ha sido que no conozco todas las llamadas de método que borran el indicador de interrupción.

Actualmente sé que lo siguiente será borrar el indicador de interrupción:

Thread.interrupted() 
Thread.sleep(long) 
Thread.join() 
Thread.join(long) 
Object.wait() 
Object.wait(long) 

¿Qué más me falta? Gracias

Respuesta

25

Parte del problema ha sido que no conozco todos los métodos de llamada que borran el indicador de interrupción.

Es importante aclarar que los métodos siguientes borrar el indicador de interrupción con sólo llamarlos:

Thread.interrupted() 
Thread.isInterrupted(true) -- added to your list 

Por esta razón Thread.currentThread().isInterrupted() siempre debe utilizarse en su lugar.

Los siguientes métodos se borrar el indicador interrumpido por inmediatamente tirar InterruptedException ya sea si se les llamó y luego el hilo se interrumpió o si el hilo se ya interrumpió y luego fueron llamados (ver código junit debajo) Entonces, no es el método que borra la bandera, arrojando la excepción.

Thread.sleep(long) 
Thread.join() 
Thread.join(long) 
Thread.join(int, long) – added to your list 
Object.wait() 
Object.wait(long) 
Object.wait(int, long) – added to your list 
BlockingQueue.put(...) – added to your list 
BlockingQueue.offer(...) – added to your list 
BlockingQueue.take(...) – added to your list 
BlockingQueue.poll(...) – added to your list 
Future.get(...) – added to your list 

Tenga en cuenta que el patrón adecuada con cualquier código que atrapa InterruptedException es inmediatamente volver a interrumpir el hilo. Hacemos esto en caso de que otros se basan en el método de thread.isInterrupted():

try { 
    ... 
} catch (InterruptedException e) { 
    // immediately re-interrupt the thread 
    Thread.currentThread().interrupt(); 
    // log the exception or [likely] quit the thread 
} 

código JUnit que demuestra algo de esto:

assertFalse(Thread.currentThread().isInterrupted()); 
// you can do this from another thread by saying: someThread.interrupt(); 
Thread.currentThread().interrupt(); 
// this method does _not_ clear the interrupt flag 
assertTrue(Thread.currentThread().isInterrupted()); 
// but this one _does_ and should probably not be used 
assertTrue(Thread.interrupted()); 
assertFalse(Thread.currentThread().isInterrupted()); 
Thread.currentThread().interrupt(); 
assertTrue(Thread.currentThread().isInterrupted()); 
try { 
    // this throws immediately because the thread is _already_ interrupted 
    Thread.sleep(1); 
    fail("will never get here"); 
} catch (InterruptedException e) { 
    // and when the InterruptedException is throw, it clears the interrupt 
    assertFalse(Thread.currentThread().isInterrupted()); 
    // we should re-interrupt the thread so other code can use interrupt status 
    Thread.currentThread().interrupt(); 
} 
assertTrue(Thread.currentThread().isInterrupted()); 
10

La convención común es la siguiente: cualquier método que arroje InterruptedException (+ Thread.interrupted()) borra el indicador de interrupción.

Por lo tanto, para que sus subprocesos sean interrumpibles, debe encontrar todos los lugares donde InterruptedException queda atrapado sin recuperarlo o restablecer el indicador de interrupción. Dado que InterruptedException es una excepción comprobada, no es difícil de hacer.

+0

Esa fue la primera vez que lancé la base de código que realicé, sin embargo, estoy enfrentando una situación en la que los programadores anteriores detectarían una Excepción general en lugar de una InterruptedException. – OverflowingStack

1

Este es un ejemplo estupendo de la diversión:

ch.qos.logback .core.AsyncAppenderBase anterior a la versión 1.1.4 atrapa y traga InterruptedException sin restablecer el indicador en el hilo.

Por lo tanto, si usa algo que se dirija a este registrador (como slf4j), silenciosamente comerá su estado de interrupción de hilo. 'Porque, quiero decir, ¿quién no verifica el estado de interrupción del hilo antes y después de cada operación de registro posible?

Cuestiones relacionadas