¿Cómo se mata un hilo en Java?

¿Cómo matas a java.lang.Thread en Java?

Vea este hilo por Sun sobre por qué han Thread.stop() . Se detalla por qué este fue un mal método y qué se debe hacer para detener de manera segura los hilos en general.

La forma en que recomiendan es usar una variable compartida como una bandera que le pide al hilo de fondo que se detenga. Esta variable puede ser configurada por un objeto diferente solicitando la terminación del hilo.

Generalmente no lo haces ..

Usted le pide que interrumpa lo que sea que esté haciendo usando Thread.interrupt () (enlace javadoc)

Una buena explicación de por qué está en el javadoc aquí (enlace técnico de java)

En Java los hilos no se eliminan, pero la detención de un hilo se realiza de forma cooperativa . Se le pide al subproceso que finalice y el subproceso se puede cerrar con gracia.

A menudo se usa un campo volatile boolean que el hilo revisa y finaliza periódicamente cuando se establece en el valor correspondiente.

No usaría un boolean para verificar si el hilo debería terminar . Si usa volatile como modificador de campo, esto funcionará de manera confiable, pero si su código se vuelve más complejo, en su lugar utiliza otros métodos de locking dentro del ciclo while, podría suceder que su código no termine o al menos tome más tiempo. como quieras

Ciertos métodos de locking de bibliotecas admiten la interrupción.

Cada hilo ya tiene un estado booleano interrumpido y debe usarlo. Se puede implementar de esta manera:

 public void run() { try { while (!interrupted()) { // ... } } catch (InterruptedException consumed) /* Allow thread to exit */ } } public void cancel() { interrupt(); } 

Código fuente adaptado de Java Concurrency in Practice . Como el método cancel() es público, puede permitir que otro hilo invoque este método como lo desee.

Una forma es establecer una variable de clase y usarla como centinela.

 Class Outer { public static volatile flag = true; Outer() { new Test().start(); } class Test extends Thread { public void run() { while (Outer.flag) { //do stuff here } } } } 

Establezca una variable de clase externa, es decir, bandera = verdadera en el ejemplo anterior. Configúralo en falso para ‘matar’ el hilo.

Hay una manera de cómo puedes hacerlo. Pero si tuviste que usarlo, o eres un mal progtwigdor o estás usando un código escrito por malos progtwigdores. Entonces, debes pensar en dejar de ser un mal progtwigdor o dejar de usar este código malo. Esta solución es solo para situaciones donde NO HAY OTRA MANERA.

 Thread f =  Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} ); m.setAccessible( true ); m.invoke( f , new ThreadDeath() ); 

Quiero agregar varias observaciones, basadas en los comentarios que se han acumulado.

  1. Thread.stop () detendrá un hilo si el administrador de seguridad lo permite.
  2. Thread.stop () es peligroso. Habiendo dicho eso, si está trabajando en un entorno JEE y no tiene control sobre el código que se llama, puede ser necesario.
  3. Nunca debe detener la detención de un hilo de trabajador contenedor. Si desea ejecutar código que tiende a bloquearse, (con cuidado) inicie un nuevo hilo de daemon y supervise, matando si es necesario.
  4. stop () crea un nuevo error ThreadDeath en la cadena de llamada y luego hace que ese Error se aplique a la cadena de destino . Por lo tanto, el seguimiento de la stack generalmente no tiene ningún valor.
  5. En JRE 6, stop () comprueba con el administrador de seguridad y luego llama a stop1 () que llama a stop0 (). stop0 () es código nativo.

Yo votaría por Thread.stop() .

Por ejemplo, tiene una operación de larga duración (como una solicitud de red). Supuestamente está esperando una respuesta, pero puede tomar tiempo y el usuario navega a otra IU. Este hilo de espera ahora es a) inútil b) problema potencial, porque cuando obtenga el resultado, es completamente inútil y desencadenará devoluciones de llamada que pueden conducir a una cantidad de errores.

Todo eso y él puede hacer un procesamiento de respuesta que podría ser intenso en la CPU. Y usted, como desarrollador, ni siquiera puede detenerlo, porque no puede tirar if (Thread.currentThread().isInterrupted()) en todo el código.

Entonces la inhabilidad de parar forzosamente un hilo es extraño.

La pregunta es bastante vaga. Si se refería a “¿cómo escribo un progtwig para que un hilo deje de ejecutarse cuando yo quiero”, entonces otras varias respuestas deberían ser útiles. Pero si quería decir “Tengo una emergencia con un servidor que no puedo reiniciar en este momento y solo necesito que muera un hilo en particular, pase lo que pase”, entonces necesita una herramienta de intervención para que coincida con herramientas de monitoreo como jstack .

Para este propósito creé jkillthread . Vea sus instrucciones de uso.

Por supuesto, está el caso en el que está ejecutando algún tipo de código no completamente confiable. (Personalmente tengo esto al permitir que los scripts cargados se ejecuten en mi entorno Java. Sí, hay una alarma de seguridad sonando en todas partes, pero es parte de la aplicación). En este desafortunado caso, ante todo, simplemente estás siendo optimista al preguntar a los guionistas para respetar algún tipo de señal booleana run / don’t-run. Su única falla decente segura es llamar al método stop en el hilo si, por ejemplo, se ejecuta más tiempo que un tiempo de espera excedido.

Pero esto es simplemente “decente”, y no absoluto, porque el código podría atrapar el error ThreadDeath (o cualquier excepción que arroje explícitamente), y no volver a lanzarlo como se supone que debe hacer un hilo caballeroso. Por lo tanto, la conclusión es que AFAIA no tiene fallas absolutas.

No hay forma de matar con gracia un hilo.

Puedes intentar interrumpir el hilo, una estrategia común es usar una píldora venenosa para enviar el mensaje y detenerse

 public class CancelSupport { public static class CommandExecutor implements Runnable { private BlockingQueue queue; public static final String POISON_PILL = “stopnow”; public CommandExecutor(BlockingQueue queue) { this.queue=queue; } @Override public void run() { boolean stop=false; while(!stop) { try { String command=queue.take(); if(POISON_PILL.equals(command)) { stop=true; } else { // do command System.out.println(command); } } catch (InterruptedException e) { stop=true; } } System.out.println(“Stopping execution”); } } 

}

 BlockingQueue queue=new LinkedBlockingQueue(); Thread t=new Thread(new CommandExecutor(queue)); queue.put(“hello”); queue.put(“world”); t.start(); Thread.sleep(1000); queue.put(“stopnow”); 

http://anandsekar.github.io/cancel-support-for-threads/

En general, no mata, detiene ni interrumpe un hilo (ni comprueba si se interrumpe ()), sino que deja que termine de forma natural.

Es simple. Puede usar cualquier ciclo junto con la variable booleana (volátil) dentro del método run () para controlar la actividad del hilo. También puede regresar desde el hilo activo al hilo principal para detenerlo.

De esta manera matas con gracia un hilo :).

Los bashs de terminación abrupta de hilos son una mala práctica de progtwigción bien conocida y evidencia de un diseño de aplicación deficiente. Todos los subprocesos de la aplicación multiproceso comparten explícita e implícitamente el mismo estado de proceso y se ven obligados a cooperar entre sí para mantener la coherencia, de lo contrario, su aplicación será propensa a los errores que serán realmente difíciles de diagnosticar. Por lo tanto, es responsabilidad del desarrollador proporcionar una garantía de tal consistencia a través de un diseño de aplicación claro y cuidadoso.

Hay dos soluciones correctas principales para las terminaciones de subprocesos controlados:

  • Uso de la bandera volátil compartida
  • Uso del par de métodos Thread.interrupt () y Thread.interrupted ().

Explicaciones buenas y detalladas de los problemas relacionados con la terminación abrupta de hilos, así como ejemplos de soluciones correctas e incorrectas para la terminación de hilos controlados se pueden encontrar aquí:

https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads

Aquí hay un par de buenas lecturas sobre el tema:

¿Qué haces con InterruptedException?

Cerrando los hilos limpiamente

No obtuve la interrupción para trabajar en Android, así que usé este método, funciona perfectamente:

 boolean shouldCheckUpdates = true; private void startupCheckForUpdatesEveryFewSeconds() { Thread t = new Thread(new CheckUpdates()); t.start(); } private class CheckUpdates implements Runnable{ public void run() { while (shouldCheckUpdates){ //Thread sleep 3 seconds System.out.println("Do your thing here"); } } } public void stop(){ shouldCheckUpdates = false; } 
    Intereting Posts