El mecanismo de interrupción de subprocesos es la forma preferida de conseguir que un subproceso (cooperante) responda a una solicitud para detener lo que está haciendo. Cualquier hilo (incluido el hilo en sí, creo) podría llamar interrupt()
a un hilo.
En la práctica, los casos de uso normales interrupt()
involucran algún tipo de marco o administrador que le dice a algún hilo de trabajo que detenga lo que están haciendo. Si el hilo de trabajo es "consciente de la interrupción", notará que ha sido interrumpido a través de una excepción, o verificando periódicamente su indicador de interrupción. Al darse cuenta de que ha sido interrumpido, un hilo de buen comportamiento abandonará lo que está haciendo y se acabará.
Suponiendo el caso de uso anterior, es probable que su código se interrumpa si se ejecuta dentro de un marco de Java o desde algún hilo de trabajo. Y cuando se interrumpe, su código debe abandonar lo que está haciendo y provocar su finalización por los medios más adecuados. Dependiendo de cómo se haya llamado su código, esto podría hacerse regresando 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 subprocesos 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 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élvalo en una excepción sin marcar, y captúrelo y regístrelo en el mismo punto en el que trata con otras excepciones inesperadas sin marcar. (Alternativamente, su aplicación podría simplemente ignorar la interrupción y continuar haciendo lo que estaba haciendo).
1) Si nunca estoy interrumpiendo otros hilos, ¿qué puede desencadenar una InterruptedException?
Un ejemplo es si sus Runnable
objetos se ejecutan usando un ExecutorService
y shutdownNow()
se llama en el servicio. Y, en teoría, cualquier grupo de subprocesos de terceros o marco de gestión de subprocesos podría hacer legítimamente algo como esto.
2) Si nunca voy a interrumpir otros hilos usando interrupt () ... ¿qué significa InterruptedException
entonces? ¿Qué se supone que debo hacer al atrapar uno? ¿Apagar mi aplicación?
Necesita analizar la base de código para averiguar qué está haciendo las interrupt()
llamadas y por qué. Una vez que se haya dado cuenta de eso, puede averiguar qué >> debe hacer su << parte de la aplicación.
Hasta que sepa por qué InterruptedException
se está lanzando, le aconsejaría tratarlo como un error grave; por ejemplo, imprima un seguimiento de pila en el archivo de registro y cierre la aplicación. (Obviamente, esa no siempre es la respuesta correcta ... pero el punto es que esto es "un error", y debe notificarse al desarrollador / mantenedor).
3) ¿Cómo puedo saber quién / qué está llamando interrupt()
?
No hay una buena respuesta a esto. Lo mejor que puedo sugerir es establecer un punto de interrupción en el Thread.interrupt()
y mirar la pila de llamadas.
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 debe tratar un
InterruptedException
solo como un "comando de salida". En cambio, debe pensar en las interrupciones como un medio para controlar el estado de ejecución de los subprocesos, de la misma manera que loObject.notify()
hace. De la misma manera que verificaría el estado actual después de despertarse de una llamada aObject.wait()
(no asume que el despertador significa que su condición de espera se ha cumplido), después de recibir un empujón con una interrupción, debe verificar por qué fue interrumpido . Generalmente hay una forma de hacer esto. Por ejemplo,java.util.concurrent.FutureTask
tiene unisCancelled()
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(); }
fuente
El problema con la pregunta es "yo". "Yo" generalmente se refiere a una sola instancia de una clase. Quiero decir con eso, que cualquier pieza particular de código de bajo nivel (clase) no debería depender de la implementación de todo el sistema. Habiendo dicho eso, debe tomar algunas decisiones "arquitectónicas" (como en qué plataforma ejecutar).
Las posibles interrupciones inesperadas provenientes del JRE son tareas canceladas
java.util.concurrent
y cierres de subprogramas.El manejo de interrupciones de subprocesos generalmente se escribe incorrectamente. Por lo tanto, sugiero la decisión arquitectónica para evitar causar interrupciones cuando sea posible. Sin embargo, las interrupciones de manejo de código siempre deben escribirse correctamente. No puedo eliminar las interrupciones de la plataforma ahora.
fuente
Puede aprender esto creando su propia clase de subproceso (extensión
java.lang.Thread
) yinterrupt()
método de anulación , en el que registra el seguimiento de la pila en, digamos, un campo String, y luego lo 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(); } }
fuente
Como ya se mencionó, otra biblioteca puede interrumpir sus hilos. Incluso si la biblioteca no tiene acceso explícito a los subprocesos de su código, aún pueden obtener la lista de subprocesos que se están ejecutando e interrumpirlos de esa manera con el siguiente método .
fuente
Creo que entiendo por qué estás un poco confundido acerca de la interrupción. Considere mis respuestas en línea:
En primer lugar, puede interrumpir otros hilos; Sé que en JCiP se menciona que nunca debes interrumpir los subprocesos que no te pertenecen; sin embargo, esta declaración debe entenderse correctamente. Lo que significa es que su código, que podría estar ejecutándose en cualquier hilo arbitrario, no debería manejar la interrupción porque, dado que 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 encapsulada la política de interrupción, no su código de tarea; ¡al menos sea cortés para poner la bandera de interrupción!
Hay muchas formas por las que aún podría haber interrupciones, pueden haber tiempos de espera, interrupciones de JVM, etc.
Debe tener mucho cuidado aquí; Si posee el hilo que lanzó InterruptedException (IE), entonces sabe qué hacer al detectarlo, digamos que puede cerrar su aplicación / servicio o puede reemplazar este hilo muerto por uno nuevo. Sin embargo, si no posee el hilo, al capturar IE, vuelva a lanzarlo más arriba en la pila de llamadas o después de hacer algo (puede estar registrando), restablezca el estado interrumpido para que el código que posee este hilo, cuando el control lo alcance, pueda aprender que el hilo fue interrumpido y, por lo tanto, tomar las medidas necesarias, ya que solo él conoce la política de interrupción.
Espero que esto haya ayudado.
fuente
El
InterruptedException
dice que una rutina puede ser interrumpido, pero no necesariamente que sea.Si no espera la interrupción, debe tratarla como lo haría con cualquier otra excepción inesperada. Si se encuentra en una sección crítica donde una excepción inesperada podría tener consecuencias atroces, podría ser mejor intentar limpiar los recursos y cerrar con elegancia (porque obtener las señales de interrupción indica que se está utilizando una aplicación bien diseñada que no depende de interrupciones de alguna manera no fue diseñado, por lo que 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.
fuente