1. Introducción
Este artículo registra algunos puntos de conocimiento sobre el mecanismo de interrupción en Java multithreading. Consiste principalmente en la diferencia entre los métodos Stop Method, Interrupted () e IsInterrupted (), y realiza un análisis simple desde la implementación del código fuente.
Hay 3 formas de terminar con los hilos de ejecución en Java
① El hilo sale normalmente, es decir, el método run () se ha ejecutado
② Use el método stop () en la clase de hilo para terminar con fuerza el hilo. Sin embargo, el método stop () ha expirado y no se recomienda usarlo
③ Utilice el mecanismo de interrupción
No hay nada que hacer cuando el hilo sale normalmente. El mecanismo de interrupción se introduce en detalle a continuación. Primero veamos el código fuente del método stop (). La clave son los comentarios sobre el código fuente. Explica por qué parar () no es seguro, ¿qué hilo se detiene mediante el método stop ()?
/*** obliga al hilo a dejar de ejecutar.* <p>* Si hay un administrador de seguridad instalado, su método <code> checkAccess </code>* se llama con <code> this </code>* como su argumento. Esto puede dar lugar a que se esté planteando un* <code> SecurityException </code> (en el hilo actual).* <p>* Si este hilo es diferente del subproceso actual (es decir, el hilo actual* está intentando detener un subproceso que no sea en sí mismo), el* Manager de seguridad <Code> CheckPermission </Code> Method (con un* <Code> RuntimeMission ("Stopthread") <///Code> argumento) se llama a* AGRADA. <code> SecurityException </code> (en el hilo actual).* <p>* El hilo representado por este hilo se ve obligado a detener lo que* esté haciendo anormalmente y lanzar un objeto* <code> Threaddeath </code> recién creado como una excepción.* <P>* Se permite detener un hilo que aún no se ha iniciado.* Si el hilo finalmente se inicia, termina inmediatamente. <code> Threaddeath </code> a menos que debe hacer una operación de limpieza* extraordinaria* (tenga en cuenta que el lanzamiento de* <code> Threaddeath </code> causa <code> finalmente </code> cláusulas de* <code> prueba </code> declaraciones que se ejecutarán antes del hilo* oficialmente muere). Si A <code> Catch </code> la cláusula captura un objeto* <code> Threaddeath </code>, es importante volver a solucionar el objeto* para que el hilo realmente muera.* <p>* El controlador de errores de nivel superior que se realiza al controlador de errores de nivel superior que reacciona de otra manera* las excepciones* excepciones no imprimen un mensaje o nocriben la aplicación* si la excepción no capacitada es una instancia de la instancia de* <Code> de otra manera. no puedo* modificar este hilo.* @see #interrupt ()* @see #checkaccess ()* @see #run ()* @see #start ()* @see Threaddeath* @see Threadgroup #UnsappageSception (Thread, Throwable)* @See SecurityManager #checkaccess (Thread)* @see SecurityManger #checkpermission* @Depreced este método es un método inesfe. Detener un hilo con* hilo. La parada hace que desbloquee todos los monitores que* ha bloqueado (como una consecuencia natural de la excepción de* <code> threaddeath </code> que se propaga la pila). Si* alguno de los objetos previamente protegidos por estos monitores estaba en* un estado inconsistente, los objetos dañados se vuelven visibles para* otros hilos, lo que potencialmente resultó en un comportamiento arbitrario. Muchos* usos de <code> stop </code> deben reemplazarse por código que simplemente* modifique alguna variable para indicar que el hilo de destino debe* dejar de ejecutar. El hilo de destino debe verificar esta variable* regularmente y volver de su método Ejecutar de manera ordenada* si la variable indica que debe dejar de funcionar. Si el hilo de destino* espera períodos largos (en una variable de condición,* por ejemplo), el método <code> interrupt </code> debe usarse para* interrumpir la espera.* Para obtener más información, consulte* <a href = "{@docroot} /../ ... Descargado? </a>.*/@Deprecedpublic final void stop () {stop (new Threaddeath ());}Como se comentó anteriormente, las líneas 9 a 16 indican que el método stop () puede detener "otros hilos". El hilo que ejecuta el método thread.stop () se llama hilo actual, mientras que el "otro hilo" es el hilo representado por el hilo del objeto que llama al método thread.stop ().
como:
public static void main (string [] args) {myThread Thread = new Mythread ... // .... thread.stop (); // ..}En el método principal, el hilo actual es el hilo principal. Se ejecuta a la línea 4 y quiere detener el hilo de "otro hilo". Este otro hilo es el hilo representado por el objeto de hilo de la nueva clase Mythread.
Las líneas 21 a 23 indican que un hilo que aún no se ha iniciado aún se puede detener. Su efecto es: cuando el hilo comienza, termina inmediatamente.
¡Los comentarios después de la línea 48 muestran profundamente por qué el método stop () está en desuso! Por qué es inseguro.
Por ejemplo, ThinkA Thread tiene monitores responsables de proteger ciertos recursos críticos, como la cantidad de transferencias bancarias. Cuando el proceso de transferencia está en progreso, el hilo principal llama al método ThreadA.stop (). Como resultado, se libera el monitor y los recursos que protege (la cantidad de transferencia) es probable que sean inconsistentes. Por ejemplo, la cuenta A ha disminuido en 100, mientras que la cuenta B no ha aumentado en 100.
Segundo, mecanismo de interrupción
Hay demasiados detalles sobre cómo usar el mecanismo de interrupción correctamente en Java. Tanto los métodos interrumpidos () como ISInterrumped () reflejan si el hilo actual está en un estado interrumpido.
① interrumpido ()
/*** prueba si el hilo actual ha sido interrumpido. El estado* <i> interrumpido </i> del hilo se borra mediante este método. En* otras palabras, si este método se llamara dos veces en sucesión, la* segunda llamada devolvería falso (a menos que el hilo actual fuera* interrumpido nuevamente, después de que la primera llamada hubiera borrado su estado de interrupción* y antes de que la segunda llamada lo hubiera examinado). ** <p> un hilo interrupido ignorado porque un hilo no estaba vivo* en el momento de la interrupción de la interrupción se reflejará en este método* que devuelve el falso* @@ret @retrurn. ha sido interrumpido;* <code> false </code> de lo contrario.* @see #isinterrupted ()* @revised.*/public static boolean interrumped () {return currentThread (). ISinterrupted (true);}De los comentarios en el código fuente, prueba el estado de interrupción del hilo actual, y este método borrará el estado de interrupción.
②isinterrupted ()
/*** prueba si este hilo ha sido interrumpido. El estado <i> interrumpido* el estado </i> del hilo no se ve afectado por este método. ** <p> Una interrupción de un hilo ignorada porque un hilo no estaba vivo* en el momento de la interrupción se reflejará mediante este método* devolviendo falso. ** @return <code> true </code> si este hilo ha sido interrumpido;* <code> falso </código> lo contrario.* @Seeee #interrumped (). iSinterrupted () {return isinterrupted (false);}Como se puede ver en los comentarios del código fuente, el método iSinterrupted () no borrará el estado de interrupción.
③Diferferencia entre el método interrumped () e ISinterrupted ()
Como se puede ver en el código fuente, ambos métodos se llaman ISInterrupted (boolean ClearInterrupted), excepto que uno con el parámetro es verdadero y el otro con el parámetro es falso.
/*** Prueba si se ha interrumpido algún hilo. El estado interrumpido* se restablece o no se basa en el valor de ClearInterrupted que se* aprobó.*/Booleano nativo privado es Interrupted (booleano ClearInterrupted);
Por lo tanto, la primera diferencia es que uno borra el bit de la bandera de interrupción y el otro no borra el bit de la bandera de interrupción.
Después de analizar el código fuente, puede ver la segunda diferencia en la declaración de retorno:
public static boolean interrumped () {return currentThread (). isinterrupted (true);}/************************/public boolean isinterrupted () {return ISinterrupted (falso);}Interrupted () prueba el estado interrumpido del hilo actual. El ISInterrupted () prueba el hilo representado por el objeto que llama al método. Uno es un método estático (prueba el estado de interrupción del hilo actual), y el otro es un método de instancia (prueba el estado de interrupción del hilo representado por el objeto de instancia).
El siguiente es un ejemplo específico para aclarar aún más esta diferencia.
Hay una clase de hilo personalizado de la siguiente manera:
public class myThread extiende el hilo {@OverridePublic Void run () {super.run (); for (int i =; i <; i ++) {System.out.println ("i =" + (i +));}}}Primero veamos el ejemplo del método interrumpido ():
public class run {public static void main (string [] args) {try {myThread Thread = nuevo MyThread (); thread.start (); thread.sleep (); thread.interrupt (); // thread.currentThread (). Interrupt (); system.out.println ("stop? ="+Thread.interrupted ()); // falsesystem.out.println ("stop? ="+Thread.interrupted (); // falso principal ¡¡¡¡¡¡¡ // ...La línea 5 inicia el hilo del hilo, y la línea 6 hace que el hilo principal duerma durante 1 segundo, de modo que el hilo del hilo tenga la oportunidad de obtener la ejecución de la CPU.
Después de que el hilo principal duerme para 1s, se reanuda la ejecución a la línea 7 y solicita interrumpir el hilo del hilo.
La línea 9 prueba si el hilo está en un estado interrumpido. ¿Qué hilo se está probando aquí? ? ? La respuesta es el hilo principal. porque:
(1) Interrupted () prueba el estado de interrupción del hilo actual
(2) El hilo principal ejecuta la declaración de la novena línea, por lo que el hilo principal es el hilo actual
Veamos el ejemplo del método iSinterrupted ():
public class run {public static void main (string [] args) {try {mythread thread = new mythread (); thread.start (); thread.sleep (); thread.interrupt (); system.println ("¿se detiene? ="+hilt.isinterrupted ()); // trueEn la línea 8, el método ISinterrupted () llamado por el objeto de subproceso. Por lo tanto, se prueba el estado de interrupción del hilo representado por el objeto de subproceso. Dado que en la línea 7, el hilo principal solicita para interrumpir el hilo del subproceso, el resultado en la línea 8 es: verdadero