java multithreading interrupt

¿Cuáles son las diferencias entre llamar a System.exit(0) y Thread.currentThread(). Interrupt() en el hilo principal de un programa Java?



multithreading (3)

Resumen

  1. thread.interrupt() no detiene un hilo. Se utiliza para la coordinación en programas multi-hilo. No lo uses a menos que sepas exactamente lo que haces.
  2. Lanzar una RuntimeException terminará (normalmente) el hilo pero no necesariamente el programa.
  3. System.exit(int) casi siempre termina el programa y devuelve un código de estado.
  4. En situaciones inusuales, System.exit(int) podría no detener el programa. Runtime.getRuntime().halt(int) por otro lado, siempre lo hace.

Interrupcion de hilo

Me temo que su primera frase es incorrecta. Thread.currentThread().interrupt() no detiene el hilo ni el programa.

Interrumpir un hilo es una forma de indicar que debería detenerse, pero es un esfuerzo cooperativo: se supone que el código en el hilo comprueba el estado interrumpido de vez en cuando y (en la mayoría de los casos, pero incluso esto es opcional) Detenerse si se ha interrumpido. Si no lo hace no pasará nada.

Específicamente, la interrupción de un subproceso (cualquier subproceso, incluido el que se está ejecutando actualmente) solo establecerá el indicador interrumpido . Ciertos métodos en la biblioteca estándar lanzarán una InterruptedException, pero esta es también una manera de indicar que el hilo ha sido interrumpido. Lo que se debe hacer en tal situación depende del código que se ejecuta en ese hilo.

Aquí están las partes relevantes del libro Java Concurrency in Practice de Brian Goetz:

El subproceso proporciona el método de interrupción para interrumpir un subproceso y para consultar si un subproceso se ha interrumpido. Cada hilo tiene una propiedad booleana que representa su estado interrumpido; la interrupción de un hilo establece este estado.

La interrupción es un mecanismo cooperativo. Un hilo no puede obligar a otro a detener lo que está haciendo y hacer otra cosa; cuando el subproceso A interrumpe el subproceso B, A simplemente solicita que B detenga lo que está haciendo cuando llega a un punto de parada conveniente, si así lo desea. interrupción, el uso más sensato de la interrupción es cancelar una actividad. Los métodos de bloqueo que responden a la interrupción facilitan la cancelación de actividades de larga duración de manera oportuna.

Excepciones y System.exit (int)

El Javadoc de System.exit(int) dice:

Termina la Java Virtual Machine actualmente en ejecución. El argumento sirve como un código de estado; por convención, un código de estado distinto de cero indica una terminación anormal.

Así que llamar a exit() (casi) definitivamente detendrá su programa. A diferencia de lanzar una RuntimeException (o un Error ), esto no puede detectarse en algún lugar de la pila de llamadas y tampoco depende de si hay otros subprocesos en ejecución. Por otro lado, una excepción no detectada finaliza el subproceso en el que se lanzó, pero si hay otros subprocesos (no daemon), el programa continuará ejecutándose.

Otra diferencia para lanzar una excepción es que exit() no imprimirá nada en la consola (como lo hace una excepción no detectada), sino que hace que el programa devuelva un código de estado específico. Los códigos de estado a veces se usan en shell o en scripts por lotes, pero aparte de eso, no son muy útiles.

Runtime.halt (int)

Finalmente (para completar el tema), me gustaría señalar una tercera posibilidad para salir de un programa Java. Cuando se System.exit(int) (o el programa termina de alguna otra manera), el tiempo de ejecución realiza un trabajo de limpieza antes de que se detenga la Máquina Virtual de Java. Esto se describe en el Javadoc de Runtime.exit(int) (que es llamado por System.exit(int) :

La secuencia de apagado de la máquina virtual consta de dos fases. En la primera fase, todos los ganchos de apagado registrados, si los hay, se inician en un orden no especificado y se les permite que se ejecuten simultáneamente hasta que finalicen. En la segunda fase, todos los finalizadores no invocados se ejecutan si se ha habilitado la finalización en la salida. Una vez hecho esto, la máquina virtual se detiene.

Si se evita que se complete cualquier gancho de cierre o finalizador, por ejemplo, debido a un deadlock , es posible que el programa nunca salga. El único método que garantiza que la JVM se detiene es Runtime.halt(int) :

Este método debe utilizarse con extrema precaución. A diferencia del método de salida, este método no hace que se inicien los enganches de cierre y no ejecuta finalizadores no invocados si se ha habilitado la finalización en la salida.

Ambos provocan que un programa deje de ejecutarse. Sin embargo, está claro que debe haber algunas diferencias en cómo esto sucede. ¿Qué son?


En una aplicación multiproceso, hay más de un hilo ejecutándose. Thread.currentThread().interrupt() solo interrumpe tu subproceso en ejecución actual, pero el subproceso restante se ejecutará, incluso si tu subproceso principal está interrumpido ...

Considerando que, System.exit(0) hace que su sistema se termine .. Y todos los hilos se eliminan ...


Si hay otros subprocesos (no daemon) en ejecución, la JVM no se cerrará si detiene el subproceso principal. System.exit () mata a todos los otros hilos.