Pregunta ¿Quién está llamando al método Java Thread interrupt () si no lo estoy?


He leído y releído Java Concurrency in Practice, he leído varios hilos aquí sobre el tema, he leído el artículo de IBM Tratando con InterruptedException y, sin embargo, hay algo que simplemente no capto, y creo que se puede dividir en dos preguntas:

  1. Si nunca más estoy interrumpiendo otros hilos, ¿qué puede desencadenar un InterruptedException?

  2. Si nunca más estoy interrumpiendo otros hilos yo mismo usando interrumpir() (decir, porque estoy usando otros medios para cancelar mis hilos de trabajo, como las píldoras venenosas y while (! cancelled) ciclo de estilo [como ambos explican en JCIP]), ¿qué hace una InterruptedException entonces, ¿significa? ¿Qué se supone que debo hacer para atrapar uno? Apagar mi aplicación?


76
2018-01-24 12:25


origen


Respuestas:


El mecanismo de interrupción de subprocesos es la forma preferida de obtener un hilo (de cooperación) para responder una solicitud para detener lo que está haciendo. Cualquier hilo (incluido el propio hilo, creo) podría llamar interrupt() en un subproceso

En la práctica, los casos de uso normal para interrupt() involucrar a algún tipo de marco o gerente diciendo algo de hilo de trabajo para detener lo que están haciendo. Si el hilo del trabajador está "a prueba de interrupciones" notará que ha sido interrumpido a través de una excepción, o al revisar periódicamente su bandera interrumpida. Al darse cuenta de que se ha interrumpido, un hilo que se comporta bien abandonaría lo que está haciendo y terminará a sí mismo.

Suponiendo que el caso de uso anterior, su código es probable que se interrumpa si se ejecuta dentro de un marco de Java o de alguna cadena de trabajo. Y cuando se interrumpe, su código debe abandonar lo que está haciendo y debe terminar por los medios más adecuados. Dependiendo de cómo se invocó su código, esto se puede hacer volviendo o lanzando alguna excepción apropiada. Pero probablemente no debería llamar System.exit(). (Su aplicación no necesariamente sabe por qué fue interrumpida, y ciertamente no sabe si hay otros hilos que deben ser interrumpidos por el marco).

Por otro lado, si su código no está diseñado para ejecutarse bajo el control de algún marco, podría argumentar que el InterruptedException es una excepción inesperada; es decir, un error. En ese caso, debe tratar la excepción como lo haría con otros errores; p.ej. envuélvalo en una excepción sin marcar, y capture y registre en el mismo punto en que trata otras excepciones no verificadas. (Alternativamente, su aplicación podría simplemente ignorar la interrupción y continuar haciendo lo que estaba haciendo).


1) Si nunca voy a interrumpir otros hilos, ¿qué puede disparar una InterruptedException?

Un ejemplo es si tu Runnable los objetos se ejecutan usando un ExecutorService y shutdownNow() se llama en el servicio. Y, en teoría, cualquier grupo de threads de terceros o un marco de administración de hilos podría hacer algo como esto legítimamente.

2) Si nunca más estoy interrumpiendo otros hilos usando interrupt () ... ¿qué hace un InterruptedExceptionentonces, ¿significa? ¿Qué se supone que debo hacer para atrapar uno? Apagar mi aplicación?

Necesitas analizar la base de código para descubrir qué está haciendo interrupt() llamadas y por qué Una vez que te hayas dado cuenta, puedes averiguar qué >> parte de tu aplicación <necesita hacer.

Hasta que sepa por qué InterruptedException está siendo lanzado, aconsejaría tratarlo como un error difícil; p.ej. imprime un stacktrace en el archivo de registro y cierra la aplicación. (Obviamente, esa no es siempre la respuesta correcta ... pero el punto es que esto es "un error", y debe llamar la atención del desarrollador / mantenedor).

3) ¿Cómo averiguo quién / qué está llamando interrupt()?

No hay una buena respuesta para esto. Lo mejor que puedo sugerir es establecer un punto de interrupción en el Thread.interrupt() y mira la pila de llamadas.


44
2018-01-24 14:41



Si decide integrar su código con otras bibliotecas, pueden llamar interrupt() en tu código p.ej. si decide en el futuro ejecutar su código dentro de un ExecutorService, entonces eso puede forzar un cierre a través de interrupt().

Para decirlo brevemente, consideraría no solo dónde se está ejecutando su código ahora, pero en qué contexto puede funcionar en el futuro. p.ej. ¿Lo vas a poner en una biblioteca? Un contenedor ? ¿Cómo lo usarán otras personas? ¿Vas a reutilizarlo?


12
2018-01-24 12:43



Como han señalado otros, interrumpir un hilo (en realidad, interrumpir una llamada de bloqueo) generalmente se usa con el propósito de salir limpiamente o cancelar una actividad en curso.

Sin embargo, no debes tratar a un InterruptedException solo como un "comando de abandono". En su lugar, debe pensar en las interrupciones como un medio para controlar el estado de ejecución de los hilos, de la misma manera que Object.notify() hace. De la misma manera que verificaría el estado actual después de despertarse de una llamada a Object.wait() (No asume que la activación significa que se ha cumplido su condición de espera), después de haberle dado un toque con una interrupción, debe verificar por qué fuiste interrumpido Usualmente hay una manera de hacer esto. Por ejemplo, java.util.concurrent.FutureTask tiene un isCancelled() método.

Muestra de código:

public void run() {
    ....
    try {
        .... // Calls that may block.
    } catch (InterruptedException e) {
        if (!running) {  // Add preferred synchronization here.
            return; // Explicit flag says we should stop running.
        }
        // We were interrupted, but the flag says we're still running.
        // It would be wrong to always exit here. The interrupt 'nudge'
        // could mean something completely different. For example, it
        // could be that the thread was blocking on a read from a particular
        // file, and now we should read from a different file.
        // Interrupt != quit (not necessarily).
    }
    ....
}
public void stop() {
    running = false; // Add preferred synchronization here.
    myThread.interrupt();
}

9
2017-10-12 08:38



El problema con la pregunta es "yo". "I" generalmente se refiere a una sola instancia de una clase. Quiero decir con eso, que cualquier pieza particular de código (clase) de bajo nivel no debe depender de la implementación de todo el sistema. Habiendo dicho eso, usted tiene que tomar algunas decisiones "arquitectónicas" (como qué plataforma ejecutar).

Las posibles interrupciones inesperadas provenientes del JRE son tareas canceladas en java.util.concurrent y cerrar applets.

El manejo de interrupciones de hilo generalmente se escribe incorrectamente. Por lo tanto, sugiero la decisión arquitectónica de evitar causar interrupciones cuando sea posible. Sin embargo, las interrupciones de manejo de código siempre deben escribirse correctamente. Ahora no puede sacar interrupciones de la plataforma.


3
2018-01-24 16:39



Puede aprender esto creando su propia clase de subprocesos (extendiendo java.lang.Thread) y anulando interrupt() método, en el que registra la pila en un campo String, por ejemplo, y luego transfiere a superinterrumpir ().

public class MyThread extends Thread {

    public volatile String interruptStacktrace; // Temporary field for debugging purpose.

    @Override
    public void interrupt() {
        interruptStacktrace = dumpStack(); // You implement it somehow...

        super.interrupt();
    }
}

2
2017-11-12 11:02



Como ya se mencionó, otra biblioteca puede interrumpir sus hilos. Incluso si la biblioteca no tiene acceso explícito a los hilos de su código, aún pueden obtener la lista de hilos que se están ejecutando e interrumpirlos de esa manera con el siguiente método.


1
2018-01-24 18:10



los InterruptedException dice que una rutina mayo ser interrumpido, pero no necesariamente eso será.

Si no espera la interrupción, debe tratarla como podría hacer con cualquier otra excepción inesperada. Si se trata de una sección crítica donde una excepción inesperada podría tener consecuencias nefastas, sería mejor tratar de limpiar los recursos y cerrar con gracia (porque obtener las señales de interrupción de que se está utilizando su aplicación bien diseñada que no depende de las interrupciones) de alguna manera no fue diseñado, y entonces debe haber algo mal). Alternativamente, si el código en cuestión es algo no crítico o trivial, es posible que desee ignorar (o registrar) la interrupción y continuar.


0
2018-01-24 13:03



Creo que entiendo por qué estás un poco confundido acerca de la interrupción. Por favor, considere mis respuestas en línea:

Si nunca más estoy interrumpiendo otros hilos, ¿qué puede desencadenar un InterruptedException?

En primer lugar, puede interrumpir otros hilos; Sé que en JCiP se menciona que nunca debes interrumpir los hilos que no te pertenecen; sin embargo, esta declaración debe ser entendida correctamente. Lo que significa es que su código, que podría estar ejecutándose en cualquier subproceso arbitrario, no debería manejar la interrupción porque, como no es el propietario del hilo, no tiene ni idea de su política de interrupción. Por lo tanto, puede solicitar la interrupción en otros hilos, pero deje que su propietario tome el curso de la acción de interrupción; tiene la política de interrupción encapsulada dentro de ella, no su código de tarea; al menos ser cortés para establecer la bandera de interrupción!

Hay muchas maneras de por qué podría haber interrupciones, pueden haber tiempos de espera, interrupciones de JVM, etc.

Si nunca más estoy interrumpiendo otros hilos usando interrupt () (digamos porque estoy usando otros medios para cancelar mis hilos de trabajo, como las píldoras de veneno y mientras (! Cancelled) style loop [como se explica en JCIP]), qué ¿Significa una InterruptedException? ¿Qué se supone que debo hacer para atrapar uno? Apagar mi aplicación?

Debes ser muy cuidadoso aquí; si posee el hilo que arrojó InterruptedException (IE), entonces sabe qué hacer después de atraparlo, digamos que puede cerrar su aplicación / servicio o puede reemplazar este hilo destruido por uno nuevo. Sin embargo, si no posee el hilo, al capturar IE lo vuelve a lanzar más arriba en la pila de llamadas o después de hacer algo (puede estar registrando), restablece el estado interrumpido para que el código que posee este hilo, cuando el control lo alcanza, pueda aprende que el hilo se ha interrumpido y, por lo tanto, haz las acciones como lo harás, ya que solo conoce la política de interrupción.

Espero que esto haya ayudado.


0
2018-03-20 18:10