Inicio del hilo:
1. Descripción de la diferencia entre inicio () y run ()
Start (): su función es iniciar un nuevo hilo, y el nuevo hilo ejecutará el método ejecutivo () correspondiente. inicio () no se puede llamar repetidamente.
run (): run () se puede llamar repetidamente al igual que los métodos de miembros ordinarios. Si llama a ejecutar () por separado, run () se ejecutará en el hilo actual, ¡y el nuevo hilo no se iniciará!
El siguiente es un código para explicar.
La clase MyThread extiende el hilo {public void run () {...}}; mythread mythread = new mythread (); mythread.start () inicia un nuevo hilo y ejecuta el método run () en el nuevo hilo.
Mythread.run () ejecutará el método run () directamente en el hilo actual, y no iniciará un nuevo hilo para ejecutar ejecutar ().
2. Ejemplo de la diferencia entre inicio () y run ()
A continuación, demuestre la diferencia entre ellos con un ejemplo simple. El código fuente es el siguiente:
// La clase de código fuente de Java MyThread extiende el hilo {public mythread (name de cadena) {super (nombre); } public void run () {System.out.println (Thread.CurrentThread (). getName ()+"está ejecutando"); }}; Demo de clase pública {public static void main (string [] args) {Thread myThread = new MyThread ("MyThread"); System.out.println (thread.currentThread (). GetName ()+"llamar mythread.run ()"); mythread.run (); System.out.println (thread.currentThread (). GetName ()+"llamar mythread.start ()"); mythread.start (); }} Resultados de ejecución:
llamada principal mythread.run () main is runningmain llame mythread.start () mythread se está ejecutando
Descripción de los resultados:
(1) Thread.CurrentThread (). GetName () se usa para obtener el nombre de "Hilo actual". El hilo actual se refiere al hilo que está programado para ejecutar en la CPU.
(2) MyThread.run () se llama en "Main Hilo Main", y el método Run () se ejecuta directamente en "Main Thread Main".
(3) MyThread.Start () comenzará "Thread Mythread". Después de que se inicia "Thread MyThread", se llamará al método run (); En este momento, el método run () se ejecuta en "hilo mythread".
Interrupciones y terminaciones de hilo
1. Hilo Interrupt: Interrupt ()
La función de Interrupt () es interrumpir el hilo.
Este hilo puede interrumpir a sí mismo; Cuando otros hilos llaman al método de interrupción () de este hilo, el permiso se verificará a través de checkAccess (). Esto puede lanzar una excepción de SecurityException.
Si el hilo está en un estado de bloqueo: llamar a Wait (), Wait (Long) o Wait (Long, int) del hilo lo convertirá en un estado de espera (bloqueo), o llamar a unirse (), unirse (largo), unirse (largo, int), dormir (largo), dormir (largo, int) del hilo también convertirá en un estado bloqueante. Si el hilo llama a su método de interrupción () cuando está bloqueando, se borrará su "estado de interrupción" y se recibirá una Excepción InterruptedException. Por ejemplo, un hilo ingresa a un estado de bloqueo a través de Wait (), y el hilo se interrumpe por interrupción (); Llamar a la interrupción () establecerá inmediatamente la bandera de interrupción del hilo en "verdadero", pero dado que el hilo está en un estado de bloqueo, el "indicador de interrupción" se despejará inmediatamente a "falso", y se generará una Excepción InterruptedException.
Si el hilo se bloquea en un selector de selección, cuando se interrumpe por interrupción (); El indicador de interrupción del hilo se establece en verdadero y se devolverá inmediatamente desde la operación de selección.
Si no pertenece a la situación mencionada anteriormente, cuando el hilo se interrumpe a través de la interrupción (), su indicador de interrupción se establecerá en "verdadero".
La interrupción de un "hilo terminado" no causará ninguna operación.
2. Terminación del hilo
¡Se recomienda que los métodos stop () y suspender () en el hilo no se usen debido a su inseguridad inherente!
A continuación, primero discutiré el método de terminación de los hilos en "estado de bloqueo" y "estado en ejecución" respectivamente, y luego resumiré un método general.
1. Terminar el hilo en el "estado de bloqueo"
Por lo general, terminamos un hilo en un "estado de bloqueo" al "interrumpir".
Cuando el hilo ingresa a un estado de bloqueo debido a que se llame Sleep (), Wait (), unirse () y otros métodos; Si la interrupción () del hilo se llama en este momento, la marca de interrupción del hilo se establece en verdadero. Dado que está en un estado de bloqueo, la bandera de interrupción se eliminará y se genera una excepción de InterruptEdException. Poner InterruptedException hasta que sea apropiado puede terminar el hilo, en la forma de la siguiente manera:
@OverridePublic void run () {try {while (true) {// Ejecutar la tarea ...}} Catch (InterruptedException IE) {// debido a una excepción de InterruptedException, ¡salga el bucle while (true) y el hilo termina! }} NOTA: Cuando la tarea se ejecuta continuamente en While (verdadero), cuando el hilo está en un estado de bloqueo, la llamada a interrupción () del hilo genera una interrupción de InterruptedException. ¡La captura interrumpida está afuera mientras (verdadero), saliendo así del bucle while (verdadero)!
Nota: La captura de interruptedException generalmente se coloca fuera del cuerpo de bucle mientras se (verdadero) bucle While (verdadero) salga cuando se genera una excepción. De lo contrario, si InterruptedException está dentro del cuerpo de bucle While (verdadero), se requiere procesamiento adicional de adición y salida. El formulario es el siguiente:
@OverridePublic Void run () {while (true) {try {// ejecutar tarea ...} catch (interruptedException IE) {// interruptedException está en el cuerpo de bucle while (true). // Cuando el hilo genera una excepción de InterruptedException, ¡mientras que (verdadero) puede continuar funcionando! Necesito salir manualmente la ruptura; }}} Nota: La excepción de InterruptedException anterior se captura dentro de WHLE (verdadero). Cuando se genera una excepción de InterruptedException, no se maneja por captura y todavía está en el cuerpo de bucle (verdadero); Para salir del cuerpo de bucle While (verdadero), es necesario realizar una operación adicional de salir del while (verdadero).
2. Terminar el hilo en "Estado en ejecución"
Por lo general, terminamos un hilo en un "estado en ejecución" "marcando". Entre ellos, incluye "Bandera de interrupción" y "Agregar bandera adicional".
(1) Termine el hilo a través de "Bandera de interrupción".
El formulario es el siguiente:
@OverridePublic void run () {while (! Isinterrupted ()) {// ejecutar tarea ...}} Descripción: ISinterrupted () determina si el indicador de interrupción del hilo es verdadero. Cuando el hilo está en estado en funcionamiento y necesitamos terminarlo; Se puede llamar al método de interrupción del hilo (), y el indicador de interrupción del hilo está marcado verdadero, es decir, ISinterrupted () devolverá verdadero. En este punto, el bucle While se saldrá.
Nota: ¡Interrupt () no termina los hilos en "Estado en ejecución"! Establece la bandera de interrupción del hilo en verdad.
(2) Pase "Agregar marcas adicionales".
El formulario es el siguiente:
privado volátil boolean bandera = true; protegido void stopTask () {flag = false;}@overridePublic void run () {while (flag) {// ejecutar tarea ...}} Descripción: Hay una etiqueta de bandera en el hilo, y su valor predeterminado es verdadero; y proporcionamos stopTask () para configurar la etiqueta de bandera. Cuando necesitamos terminar el hilo, llamar al método stopTask () del hilo puede hacer que el hilo salga del bucle while.
Nota: La bandera se define como el tipo volátil para garantizar la visibilidad de la bandera. Es decir, después de que otros hilos modifiquen el indicador a través de stopTask (), este hilo puede ver el valor de la bandera modificado.
Completos de los métodos de terminación de los hilos en el "estado de bloqueo" y el "estado en ejecución", los hilos de terminación más comunes son los siguientes:
@OverridePublic Void run () {try {// 1. ISInterrupted () garantiza que el hilo finalizará siempre que la interrupción esté marcada verdadera. while (! IsInterrupted ()) {// Ejecutar tarea ...}} Catch (InterruptedException IE) {// 2. La excepción de InterruptedException garantiza que cuando ocurre una excepción de InterruptedException, el hilo se termina. }} 3. Ejemplo de hilo de terminación
La interrupción () a menudo se usa para terminar un hilo de "estado de bloqueo". Consulte el siguiente ejemplo:
// Demo1.Java La clase de código fuente MyThread extiende el hilo {public mythread (name de cadena) {super (nombre); } @Override public void run () {try {int i = 0; while (! isinterrupted ()) {thread.sleep (100); // dormir 100 ms i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") bucle"+i); }} Catch (InterruptedException e) {System.out.println (Thread.CurrentThread (). GetName ()+"("+this.getState ()+") Catch InterruptedException."); }}} public class Demo1 {public static void main (string [] args) {try {Thread t1 = new Mythread ("T1"); // Cree un nuevo "Hilo T1" System.out.println (t1.getName ()+"("+t1.getState ()+") es nuevo"); t1.start (); // Iniciar "Hilo T1" System.out.println (t1.getName ()+"("+t1.getState ()+") se inicia."); // El hilo principal duerme durante 300 ms, y luego el hilo principal envía una instrucción de "interrupción" a T1. Thread.Sleep (300); t1.interrupt (); System.out.println (t1.getName ()+"("+t1.getState ()+") se interrumpe."); // El hilo principal duerme durante 300 ms y luego verifica el estado de T1. Thread.Sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") se interrumpe ahora."); } catch (InterruptedException e) {E.PrintStackTrace (); }}} Resultados de ejecución:
t1 (nuevo) es nuevo.t1 (runnable) se inicia.t1 (runnable) bucle 1T1 (runnable) bucle 2t1 (timed_waiting) se interrumpe.
Descripción de los resultados:
(1) El hilo principal principal crea el hilo T1 a través de un nuevo mythread ("T1"), y luego comienza el hilo T1 a T1.Start ().
(2) Después de comenzar T1, su bandera de interrupción se verificará continuamente. Si el indicador de interrupción es "falso", dormirá durante 100 ms.
(3) Después de que T1 duerme, cambiará al rostro principal principal; Cuando el hilo principal se ejecute nuevamente, t1.interrupt () se ejecutará para interrumpir el hilo T1. Después de que T1 reciba la instrucción de interrupción, el indicador de interrupción de T1 se establecerá en "Falso" y se lanzará una Excepción InterruptedException. En el método Run () de T1, es una excepción capturada fuera del cuerpo del bucle mientras; Por lo tanto, el bucle termina.
Hicimos una pequeña modificación al resultado anterior y movimos el bloque de código que atrapó la excepción de InterruptedException en el método run () al cuerpo de bucle while.
// Demo2.Java La clase de código fuente MyThread extiende el hilo {public mythread (name de cadena) {super (nombre); } @Override public void run () {int i = 0; while (! isinterrupted ()) {try {thread.sleep (100); // Sleep para 100ms} Catch (InterruptedException IE) {System.out.println (Thread.CurrentThread (). GetName ()+"("+this.getState ()+") Catch InterruptedException."); } i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") bucle"+i); }}} public class Demo2 {public static void main (string [] args) {try {Thread t1 = new Mythread ("T1"); // Cree un nuevo "Hilo T1" System.out.println (t1.getName ()+"("+t1.getState ()+") es nuevo"); t1.start (); // Iniciar "Hilo T1" System.out.println (t1.getName ()+"("+t1.getState ()+") se inicia."); // El hilo principal duerme durante 300 ms, y luego el hilo principal envía una instrucción de "interrupción" a T1. Thread.Sleep (300); t1.interrupt (); System.out.println (t1.getName ()+"("+t1.getState ()+") se interrumpe."); // El hilo principal duerme durante 300 ms y luego verifica el estado de T1. Thread.Sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") se interrumpe ahora."); } catch (InterruptedException e) {E.PrintStackTrace (); }}} Resultados de ejecución:
t1 (nuevo) es nuevo.t1 (runnable) se inicia.t1 (runnable) bucle 1t1 (runnable) bucle 2t1 (timed_waiting) se interrumpe.t1 (runnable) capt interruptedException.t1 (runnable) bucle 3t1 (runnable) loop 4t1 (runnable) loop 5t1 (timed_waiting) se interrogado) 6T1 (runnable) bucle 7t1 (runnable) bucle 8t1 (runnable) bucle 9 ...
Descripción de los resultados:
¡El programa ha entrado en un bucle muerto!
¿Por qué está sucediendo esto? Esto se debe a que T1 se interrumpe por interrupción () cuando está "esperando (bloquear) el estado". En este momento, se borra el indicador de interrupción [que se interrumpe () devolverá falso], y se lanza una excepción de InterruptEdException [esta excepción se captura en el cuerpo de bucle mientras]. Por lo tanto, T1 entrará naturalmente en un círculo vicioso.
Para resolver este problema, necesitamos un procesamiento adicional para salir del bucle While al atrapar la excepción. Por ejemplo, agregar descanso o regresar a MyThread Catch (InterruptedException) puede resolver el problema.
Aquí hay un ejemplo de un hilo que termina un "estado de estado" al "agregar etiquetas adicionales":
// Demo3.Java La clase de código fuente myThread extiende el hilo {Flagador booleano volátil privado = true; public void stopTask () {flag = false; } public mythread (nombre de cadena) {super (nombre); } @Override public void run () {sincronizado (this) {try {int i = 0; while (flag) {thread.sleep (100); // dormir 100 ms i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") bucle"+i); }} capt (interruptedException IE) {system.out.println (thread.currentThread (). getName ()+"("+this.getState ()+") Catch InterruptedException."); }}}} public class Demo3 {public static void main (string [] args) {try {mythread t1 = new mythread ("t1"); // Cree un nuevo "Hilo T1" System.out.println (t1.getName ())+"("+t1.getState ()+") es nuevo"); t1.start (); // Iniciar "Hilo T1" System.out.println (t1.getName ()+"("+t1.getState ()+") se inicia."); // El hilo principal duerme durante 300 ms, y luego el hilo principal envía una instrucción de "interrupción" a T1. Thread.Sleep (300); t1.stoptask (); System.out.println (t1.getName ()+"("+t1.getState ()+") se interrumpe."); // El hilo principal duerme durante 300 ms y luego verifica el estado de T1. Thread.Sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") se interrumpe ahora."); } catch (InterruptedException e) {E.PrintStackTrace (); }}} Resultados de ejecución:
T1 (nuevo) es nuevo.t1 (runnable) se inicia.