2010-07-02 17 views
9

Estoy usando el CountDownLatch para sincronizar un proceso de inicialización entre dos hilos y me preguntaba sobre el manejo correcto del InterruptedException que podría arrojar.CountDownLatch InterruptedException

el código que escribió inicialmente era la siguiente:

private CountDownLatch initWaitHandle = new CountDownLatch(1); 
    /** 
    * This method will block until the thread has fully initialized, this should only be called from different threads Ensure that the thread has started before this is called. 
    */ 
    public void ensureInitialized() 
    { 
     assert this.isAlive() : "The thread should be started before calling this method."; 
     assert Thread.currentThread() != this, "This should be called from a different thread (potential deadlock)"; 
     while(true) 
     { 
      try 
      { 
       //we wait until the updater thread initializes the cache 
       //that way we know 
       initWaitHandle.await(); 
       break;//if we get here the latch is zero and we are done 
      } 
      catch (InterruptedException e) 
      { 
       LOG.warn("Thread interrupted", e); 
      } 
     } 
    } 

¿Este patrón tiene sentido? Básicamente es una buena idea ignorar el InterruptedException, solo sigue esperando hasta que tenga éxito. Supongo que simplemente no entiendo las situaciones en las que esto sería interrumpido, así que no sé si debería manejarlas de manera diferente.

¿Por qué se arrojaría una InterruptedException aquí, cuál es la mejor práctica para manejarla?

Respuesta

9

Esto es exactamente lo que no debe hacer por InterruptedException. Un InterruptedException es básicamente una solicitud cortés para que termine el hilo. El hilo debe limpiar y salir lo antes posible.

IBM tiene un buen artículo publicado en esto: http://www.ibm.com/developerworks/java/library/j-jtp05236.html

Esto es lo que haría:

// Run while not interrupted. 
while(!(Thread.interrupted()) 
{ 
    try 
    { 
     // Do whatever here. 
    } 
    catch(InterruptedException e) 
    { 
     // This will cause the current thread's interrupt flag to be set. 
     Thread.currentThread().interrupt(); 
    } 
} 

// Perform cleanup and exit thread. 

La ventaja de hacerlo de esta manera es así: Si el hilo se interrumpe mientras está en un bloqueo método, el bit de interrupción no se establecerá y se lanza un InterruptedException en su lugar. Si el hilo se interrumpe mientras no está en un método de bloqueo, se establecerá el bit interrumpido y no se lanzará ninguna excepción. Por lo tanto, al llamar al interrupt() para establecer el indicador en una excepción, ambos casos se están normalizando para el primer caso, que luego se verifica mediante el bucle condicional.

Como una ventaja adicional, esto también le permite detener su hilo simplemente interrumpiéndolo, en lugar de inventar su propio mecanismo o interfaz para establecer una bandera booleana que haga exactamente lo mismo.

+0

Gah Traté de corregir el formato y se produjo un conflicto de edición. No tengo opción de retroceder. ¡Lo siento! –

+0

Ya lo enrollé. ¡Gracias por la ayuda! Me di cuenta de que estaba mal, pero decidí corregirlo al mismo tiempo que escribía el muro de texto después. – jdmichal

+0

En realidad, no, estoy realmente acostumbrado a Wikipedia, donde hace clic en deshacer en la edición que desea deshacer, no en la revisión que desea deshacer ** a **. –

2

Si no prevé ninguna razón legítima que la Thread podría ser interrumpido y no se me ocurre ninguna reacción razonable a ella, yo diría que debe hacer

catch (InterruptedException e){ 
     throw new AssertionError("Unexpected Interruption",e); 
} 

De esta manera la aplicación se claramente falla si ocurre tal interrupción, por lo que es más fácil descubrirlo durante la prueba. Luego, puede pensar cómo la aplicación debería manejar eso, o si hay algún problema en el diseño.

Cuestiones relacionadas