¿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 que trata con InterruptedException y, sin embargo, hay algo que simplemente no entiendo, que creo que puede romperse. hacia abajo en dos preguntas:

  1. Si nunca más voy a interrumpir otros hilos, ¿qué puede desencadenar una InterruptedException ?

  2. 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?

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 a interrupt() en un hilo.

En la práctica, los casos de uso normales para interrupt() implican algún tipo de marco o gerente que dice algo 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 notar que se ha interrumpido, un hilo que se comporta bien abandonaría lo que está haciendo y se acabaría.

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 a 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 framework, podría argumentar que 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; por ejemplo, envuélvala en una excepción sin marcar, y capture y registre en el mismo punto en que trata otras excepciones inesperadas 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 sus objetos Runnable se ejecutan utilizando un ExecutorService y se llama a shutdownNow() 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é significa una InterruptedException ? ¿Qué se supone que debo hacer para atrapar uno? Apagar mi aplicación?

Necesitará analizar la base de código para descubrir qué hace las llamadas de interrupt() y por qué. Una vez que te hayas dado cuenta, puedes averiguar qué >> parte de tu aplicación

Hasta que sepa por qué se lanza InterruptedException , aconsejaría tratarlo como un error difícil; por ejemplo, imprima un stacktrace en el archivo de registro y cierre 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 a interrupt() ?

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

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

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

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

Sin embargo, no debe tratar una 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 subprocesos, de forma muy similar a como lo hace Object.notify() . De la misma forma que verificaría el estado actual después de despertar 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 haber recibido una interrupción, debería verifica por qué fuiste interrumpido. Usualmente hay una manera de hacer esto. Por ejemplo, java.util.concurrent.FutureTask tiene un método isCancelled() .

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(); } 

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 cierre de 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.

Puede aprender esto creando su propia clase de subproceso (extendiendo java.lang.Thread ) y reemplazando el método de interrupt() , en el cual registra la stack en, por ejemplo, un campo de Cadena, y luego transfiere a super.interrupt ().

 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(); } } 

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 .

La InterruptedException dice que una rutina puede ser interrumpida, pero no necesariamente así 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.

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 voy a interrumpir otros hilos, ¿qué puede desencadenar una 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 statement 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 stack 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.