¿Qué hace java.lang.Thread.interrupt ()?

Respuestas:

251

Thread.interrupt()establece el estado / indicador interrumpido del hilo objetivo. Luego, el código que se ejecuta en ese hilo de destino PUEDE sondear el estado interrumpido y manejarlo adecuadamente. Algunos métodos que bloquean Object.wait()pueden consumir el estado interrumpido inmediatamente y generar una excepción apropiada (generalmente InterruptedException)

La interrupción en Java no es preventiva. Dicho de otro modo, ambos hilos deben cooperar para procesar la interrupción correctamente. Si el hilo objetivo no sondea el estado interrumpido, la interrupción se ignora efectivamente.

El sondeo se realiza a través del Thread.interrupted()método que devuelve el estado interrumpido del subproceso actual Y borra ese indicador de interrupción. Por lo general, el hilo podría hacer algo como lanzar InterruptedException.

EDITAR (de los comentarios de Thilo): algunos métodos API han incorporado el manejo de interrupciones. De la parte superior de mi cabeza esto incluye.

  • Object.wait()` Thread.sleep()` yThread.join()
  • La mayoría de las java.util.concurrentestructuras
  • Java NIO (pero no java.io) y NO usa InterruptedException, sino que usa ClosedByInterruptException.

EDITAR (de la respuesta de @ thomas-pornin a exactamente la misma pregunta para completar)

La interrupción del hilo es una forma suave de empujar un hilo. Se usa para dar a los hilos la oportunidad de salir limpiamente , en lugar de Thread.stop()eso es más como disparar el hilo con un rifle de asalto.

Mike Q
fuente
22
Tenga en cuenta que métodos como dormir o esperar hacen este tipo de sondeo y lanzan InterruptedException por sí mismos.
Thilo
1
Si está utilizando E / S de archivos interrumpibles, el efecto no será tan suave. Por lo general, obtendrá corrupción de archivos.
Marko Topolnik el
si está mencionando Thread.interrupted, parece que debería mencionarse que también hay un indicador Thread.isInterrupted, que no borra el indicador, lo que lo hace generalmente más apropiado para su uso por los desarrolladores de aplicaciones.
Nathan Hughes
67

¿Qué es la interrupción?

Una interrupción es una indicación a un hilo de que debe detener lo que está haciendo y hacer otra cosa. Depende del programador decidir exactamente cómo responde un hilo a una interrupción, pero es muy común que el hilo termine.

¿Cómo se implementa?

El mecanismo de interrupción se implementa mediante un indicador interno conocido como estado de interrupción. Invocar Thread.interrupt establece esta bandera. Cuando un subproceso busca una interrupción invocando el método estático Thread.interrupted, el estado de la interrupción se borra. El Thread.isInterrupted no estático, que es utilizado por un hilo para consultar el estado de interrupción de otro, no cambia el indicador de estado de interrupción.

Cita de Thread.interrupt()API :

Interrumpe este hilo. Primero se invoca el método checkAccess de este hilo, lo que puede provocar una SecurityException.

Si este hilo está bloqueado en una invocación de los métodos wait (), wait (long) o wait (long, int) de la clase Object, o de join (), join (long), join (long, int) , sleep (long) o sleep (long, int), métodos de esta clase, entonces su estado de interrupción se borrará y recibirá una InterruptedException.

Si este hilo se bloquea en una operación de E / S en un canal interrumpible, entonces el canal se cerrará, se establecerá el estado de interrupción del hilo y el hilo recibirá una ClosedByInterruptException.

Si este subproceso está bloqueado en un selector, se establecerá el estado de interrupción del subproceso y volverá inmediatamente de la operación de selección, posiblemente con un valor distinto de cero, como si se invocara el método de activación del selector.

Si ninguna de las condiciones anteriores se cumple, se establecerá el estado de interrupción de este hilo.

Mira esto para comprender completamente lo mismo:

http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

YoK
fuente
Esto es obedecer una explicación parcial. También interrumpe los métodos interrumpibles.
Marqués de Lorne
@EJP Esta pregunta es sobre qué es el método Thread.interrupt () y cómo funciona. Creo que lo que sea que haya publicado con un enlace, responde lo que se pregunta. ¿Todavía no entiendo lo que deseas?
YoK
Deseo que corrija su declaración parcialmente incorrecta de que está implementada por una bandera. Eso es solo una parte de la historia. Me parece bastante claro.
Marqués de Lorne
@EJP Gracias. Ahora entiendo lo que estabas diciendo. He actualizado mi respuesta y agregué el documento de API para el método. Esto cubre la parte de métodos interrumpibles que faltaba en mi respuesta. Espero que mi respuesta se vea completa ahora :).
YoK
13

Si el hilo objetivo ha estado esperando (llamando wait(), o algún otro método relacionado que esencialmente haga lo mismo, como sleep()), se interrumpirá, lo que significa que deja de esperar lo que estaba esperando y en su lugar recibe una InterruptedException.

Depende completamente del hilo (el código que llamó wait()) decidir qué hacer en esta situación. No termina automáticamente el hilo.

A veces se usa en combinación con una bandera de terminación. Cuando se interrumpe, el hilo puede verificar esta bandera y luego cerrarse. Pero de nuevo, esto es solo una convención.

Thilo
fuente
9 años de edad, respuesta sin edad! +1
snr
10

Para completar, además de las otras respuestas, si el hilo se interrumpe antes de bloques en Object.wait(..)o Thread.sleep(..)etc., esto es equivalente a que ser interrumpido inmediatamente después de bloqueo en ese método , como muestra el siguiente ejemplo.

public class InterruptTest {
    public static void main(String[] args) {

        Thread.currentThread().interrupt();

        printInterrupted(1);

        Object o = new Object();
        try {
            synchronized (o) {
                printInterrupted(2);
                System.out.printf("A Time %d\n", System.currentTimeMillis());
                o.wait(100);
                System.out.printf("B Time %d\n", System.currentTimeMillis());
            }
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("C Time %d\n", System.currentTimeMillis());

        printInterrupted(3);

        Thread.currentThread().interrupt();

        printInterrupted(4);

        try {
            System.out.printf("D Time %d\n", System.currentTimeMillis());
            Thread.sleep(100);
            System.out.printf("E Time %d\n", System.currentTimeMillis());
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("F Time %d\n", System.currentTimeMillis());

        printInterrupted(5);

        try {
            System.out.printf("G Time %d\n", System.currentTimeMillis());
            Thread.sleep(100);
            System.out.printf("H Time %d\n", System.currentTimeMillis());
        } catch (InterruptedException ie) {
            System.out.printf("WAS interrupted\n");
        }
        System.out.printf("I Time %d\n", System.currentTimeMillis());

    }
    static void printInterrupted(int n) {
        System.out.printf("(%d) Am I interrupted? %s\n", n,
                Thread.currentThread().isInterrupted() ? "Yes" : "No");
    }
}

Salida:

$ javac InterruptTest.java 

$ java -classpath "." InterruptTest
(1) Am I interrupted? Yes
(2) Am I interrupted? Yes
A Time 1399207408543
WAS interrupted
C Time 1399207408543
(3) Am I interrupted? No
(4) Am I interrupted? Yes
D Time 1399207408544
WAS interrupted
F Time 1399207408544
(5) Am I interrupted? No
G Time 1399207408545
H Time 1399207408668
I Time 1399207408669

Implicación: si realiza un bucle como el siguiente, y la interrupción ocurre en el momento exacto en que el control se ha ido Thread.sleep(..)y está dando la vuelta al bucle, la excepción seguirá ocurriendo. Por lo tanto, es perfectamente seguro confiar en que la excepción InterruptedException sea lanzada de manera confiable después de que el hilo haya sido interrumpido :

while (true) {
    try {
        Thread.sleep(10);
    } catch (InterruptedException ie) {
        break;
    }
}
Evgeni Sergeev
fuente
4

La interrupción de subprocesos se basa en el estado de interrupción del indicador . Para cada subproceso, el valor predeterminado del estado de interrupción se establece en falso . Cada vez que se llama al método interrupt () en el hilo, el estado de interrupción se establece en verdadero .

  1. Si el estado de interrupción = verdadero (interrupt () ya llamado en el hilo), ese hilo en particular no puede ir a dormir. Si se llama a dormir en ese hilo, se produce una excepción interrumpida. Después de lanzar una excepción nuevamente, el indicador se establece en falso.
  2. Si el subproceso ya está en suspensión y se llama a interrupt () , el subproceso saldrá del estado de suspensión y arrojará la excepción interrumpida.
akash G
fuente
1

interrupción pública nula ()

Interrumpe este hilo.

A menos que el subproceso actual se interrumpa, lo que siempre está permitido, se invoca el método checkAccess de este subproceso, lo que puede provocar una excepción SecurityException.

Si este hilo está bloqueado en una invocación de los métodos wait (), wait (long) o wait (long, int) de la clase Object, o de join (), join (long), join (long, int) , sleep (long) o sleep (long, int), métodos de esta clase, luego se borrará su estado de interrupción y recibirá una excepción interrumpida.

Si este hilo se bloquea en una operación de E / S en un canal interrumpible, entonces el canal se cerrará, se establecerá el estado de interrupción del hilo y el hilo recibirá una ClosedByInterruptException.

Si este subproceso está bloqueado en un selector, se establecerá el estado de interrupción del subproceso y volverá inmediatamente de la operación de selección, posiblemente con un valor distinto de cero, como si se invocara el método de activación del selector.

Si ninguna de las condiciones anteriores se cumple, se establecerá el estado de interrupción de este hilo.

Interrumpir un hilo que no está vivo no necesita tener ningún efecto.

Throws: SecurityException - si el hilo actual no puede modificar este hilo

Ajeet Ganga
fuente
1

El método Thread.interrupt () establece el indicador interno de "estado de interrupción". Por lo general, ese indicador se verifica mediante el método Thread.interrupted ().

Por convención, cualquier método que exista a través de InterruptedException debe borrar el indicador de estado de interrupción.

Anatoliy Shuba
fuente