¿Cuándo Thread.sleep de Java lanza InterruptedException?

110

¿Cuándo Thread.sleep de Java lanza InterruptedException? ¿Es seguro ignorarlo? No estoy haciendo ningún subproceso múltiple. Solo quiero esperar unos segundos antes de reintentar alguna operación.

Manki
fuente
1
Depende en qué sentido te refieres a "ignorar". InterruptedExceptiones una excepción capturada, por lo que no se puede compilar a menos que manipule o declarar este tipo de excepción en cualquier método que se une o duerme una Threado llamadas wait()sobre Object.
8bitjunkie

Respuestas:

41

Por lo general, NO debe ignorar la excepción. Eche un vistazo al siguiente documento:

No tragues las interrupciones

A veces, lanzar InterruptedException no es una opción, como cuando una tarea definida por Runnable llama a un método interrumpible. En este caso, no puede volver a lanzar InterruptedException, pero tampoco quiere hacer nada. Cuando un método de bloqueo detecta una interrupción y lanza InterruptedException, borra el estado interrumpido. Si detecta InterruptedException pero no puede volver a lanzarla, debe conservar la evidencia de que la interrupción ocurrió para que el código más arriba en la pila de llamadas pueda conocer la interrupción y responder a ella si así lo desea. Esta tarea se logra llamando a interrupt () para "reinterrumpir" el hilo actual, como se muestra en el Listado 3. Como mínimo, siempre que detecte InterruptedException y no vuelva a lanzarlo, vuelva a interrumpir el hilo actual antes de regresar.

public class TaskRunner implements Runnable {
    private BlockingQueue<Task> queue;

    public TaskRunner(BlockingQueue<Task> queue) { 
        this.queue = queue; 
    }

    public void run() { 
        try {
             while (true) {
                 Task task = queue.take(10, TimeUnit.SECONDS);
                 task.execute();
             }
         }
         catch (InterruptedException e) { 
             // Restore the interrupted status
             Thread.currentThread().interrupt();
         }
    }
}

Vea el documento completo aquí:

http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html?ca=drs-

Benny Bottema
fuente
38

Si InterruptedExceptionse lanza un, significa que algo quiere interrumpir (generalmente terminar) ese hilo. Esto se activa mediante una llamada al interrupt()método threads . El método de espera detecta eso y lanza unInterruptedException para que el código de captura pueda manejar la solicitud de terminación de inmediato y no tenga que esperar hasta que finalice el tiempo especificado.

Si lo usa en una aplicación de un solo subproceso (y también en algunas aplicaciones de varios subprocesos), esa excepción nunca se activará. No recomendaría ignorarlo al tener una cláusula de captura vacía. El lanzamiento del InterruptedExceptionborra el estado interrumpido del hilo, por lo que si no se maneja correctamente, esa información se pierde. Por lo tanto, propondría ejecutar:

} catch (InterruptedException e) {
  Thread.currentThread().interrupt();
  // code for stopping current task so thread stops
}

Lo que establece ese estado de nuevo. Después de eso, termina la ejecución. Este sería un comportamiento correcto, incluso si no se utiliza nunca.

Lo que podría ser mejor es agregar esto:

} catch (InterruptedException e) {
  throw new RuntimeException("Unexpected interrupt", e);
}

... declaración al bloque de captura. Eso básicamente significa que nunca debe suceder. Entonces, si el código se reutiliza en un entorno en el que podría suceder, se quejará de ello.

cristiano
fuente
5
Las afirmaciones en Java están desactivadas de forma predeterminada . Así que es mejor lanzar un RuntimeException.
Evgeni Sergeev
11

El boletín de Java Specialists (que puedo recomendar sin reservas) tenía un artículo interesante sobre esto y cómo manejar el InterruptedException. Vale la pena leerlo y digerirlo.

Brian Agnew
fuente
1
¿Qué dice?
theonlygusti
5

Los métodos como sleep()y wait()de clase Threadpueden arrojar un InterruptedException. Esto sucederá si algún otro threadquisiera interrumpir al threadque está esperando o durmiendo.

usuario7805041
fuente
3

Una forma sólida y fácil de manejarlo en código de un solo hilo sería capturarlo y volver a ejecutarlo en una RuntimeException, para evitar la necesidad de declararlo para cada método.

estrella azul
fuente
-7

Por InterruptedExceptionlo general, se lanza cuando se interrumpe el sueño.

BrutalOst
fuente
13
Eso es incorrecto, ya que no es el sueño en sí lo que se interrumpe, sino el Thread que lo ejecuta. Interrumpido es un estado de subproceso. Simplemente conduce a la salida del método de sueño.
ubuntudroid