stop - ¿Cómo matas a un hilo en Java?
stop thread java 8 (14)
Aquí hay un par de buenas lecturas sobre el tema:
¿Cómo matas un java.lang.Thread
en Java?
En Java, los subprocesos no se eliminan, pero la detención de un subproceso se realiza de forma cooperativa . Se le pide al hilo que termine y el hilo puede cerrarse con gracia.
A menudo se usa un campo volatile boolean
que el hilo verifica y termina 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, ya que en su lugar utiliza otros métodos de bloqueo dentro del bucle while, puede suceder que su código no termine en absoluto o al menos tarde más. como quieras
Ciertos métodos de bloqueo de biblioteca admiten interrupción.
Cada subproceso ya tiene un estado interrumpido de bandera booleana y debe utilizarlo. Se puede implementar así:
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 . Ya que el método cancel()
es público, puedes dejar que otro hilo invoque este método como quisieras.
En general no lo haces ..
Le pides que interrumpa lo que esté haciendo usando Thread.interrupt () (enlace javadoc)
Una buena explicación de por qué está en el javadoc aquí (enlace de nota técnica de Java)
Generalmente no mata, detiene o interrumpe un hilo (o verifica si está interrumpido ()), pero deja que termine de forma natural.
Es simple. Puede usar cualquier bucle junto con la variable booleana (volátil) dentro del método run () para controlar la actividad del hilo. También puede volver del hilo activo al hilo principal para detenerlo.
De esta manera matas con gracia un hilo :).
Hay una forma en que puedes hacerlo. Pero si tuvo que usarlo, o bien es un mal programador o está utilizando un código escrito por malos programadores. Entonces, debes pensar en dejar de ser un mal programador o dejar de usar este código malo. Esta solución es solo para situaciones en las que NO HAY OTRA MANERA.
Thread f = <A thread to be stopped>
Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} );
m.setAccessible( true );
m.invoke( f , new ThreadDeath() );
La pregunta es bastante vaga. Si quiso decir "cómo escribo un programa para que un subproceso deje de ejecutarse cuando así lo desee", entonces otras respuestas deberían ser útiles. Pero si quería decir "Tengo una emergencia con un servidor, no puedo reiniciarlo ahora mismo y solo necesito un hilo en particular para morir, pase lo que pase", entonces necesita una herramienta de intervención que coincida con las herramientas de monitoreo como jstack
.
Para este propósito he creado jkillthread . Vea sus instrucciones de uso.
Los intentos de terminación abrupta de subprocesos son una mala práctica conocida de la programación 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 dicha consistencia a través de un diseño de la aplicación cuidadoso y claro.
Hay dos soluciones correctas principales para las terminaciones de hilos controlados:
- Uso de la bandera volátil compartida.
- Uso del par de métodos Thread.interrupt () y Thread.interrupted ().
Aquí puede encontrar una buena y detallada explicación de los problemas relacionados con la abrupta terminación de subprocesos, así como ejemplos de soluciones incorrectas y correctas para la terminación de subprocesos controlados:
No conseguí que la interrupción funcionara 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;
}
No hay manera de matar con gracia un hilo.
Puedes intentar interrumpir el hilo, una estrategia común es usar una pastilla venenosa para enviar un mensaje al hilo para que se detenga
public class CancelSupport {
public static class CommandExecutor implements Runnable {
private BlockingQueue<String> queue;
public static final String POISON_PILL = “stopnow”;
public CommandExecutor(BlockingQueue<String> 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<String> queue=new LinkedBlockingQueue<String>();
Thread t=new Thread(new CommandExecutor(queue));
queue.put(“hello”);
queue.put(“world”);
t.start();
Thread.sleep(1000);
queue.put(“stopnow”);
Por supuesto, existe el caso en el que está ejecutando algún tipo de código no completamente confiable. (Personalmente, tengo esto al permitir que los guiones cargados se ejecuten en mi entorno Java. Sí, suena la campana de alarma de seguridad en todas partes, pero es parte de la aplicación). para respetar algún tipo de señal de ejecución / no booleano. Su única solución segura a prueba de fallos es llamar al método de detención en el hilo si, por ejemplo, se ejecuta durante más tiempo que un tiempo de espera.
Pero, esto es simplemente "decente", y no absoluto, porque el código podría detectar el error ThreadDeath (o la excepción que usted haya lanzado explícitamente), y no hacerlo de nuevo como se supone que debe hacer un hilo de caballeros. Por lo tanto, el resultado final es AFAIA, no existe un sistema de seguridad absoluto.
Quiero agregar varias observaciones, basadas en los comentarios que se han acumulado.
- Thread.stop () detendrá un hilo si el administrador de seguridad lo permite.
- Thread.stop () es peligroso. Dicho esto, si está trabajando en un entorno JEE y no tiene control sobre el código que se está llamando, puede ser necesario.
- Nunca debes detener un hilo trabajador de contenedores. Si desea ejecutar código que tiende a colgarse, (con cuidado) inicie un nuevo subproceso de demonio y lo supervise, matándolo si es necesario.
- stop () crea un nuevo error ThreadDeath en el subproceso de llamada y luego hace que ese error se aplique al subproceso de destino . Por lo tanto, la traza de pila generalmente no tiene valor.
- En JRE 6, stop () verifica con el administrador de seguridad y luego llama a stop1 () que llama a stop0 (). stop0 () es el código nativo.
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, flag = true en el ejemplo anterior. Establézcalo en falso para "matar" el hilo.
Vea este hilo de Sun sobre por qué desaprobaron Thread.stop()
. Entra en detalles acerca de por qué este fue un mal método y qué se debe hacer para detener los hilos de forma segura en general.
La forma en que lo 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 que solicita la terminación del hilo.
Yo votaría por Thread.stop()
.
Como por ejemplo, tiene una operación de larga duración (como una solicitud de red). Supuestamente está esperando una respuesta, pero puede llevar tiempo y el usuario navegar a otra interfaz de usuario. Este hilo en espera ahora es a) inútil b) problema potencial porque cuando obtiene un resultado, es completamente inútil y activará devoluciones de llamada que pueden llevar a un número de errores.
Todo eso y él puede hacer un procesamiento de respuesta que podría ser intenso para la CPU. Y usted, como desarrollador, ni siquiera puede detenerlo, porque no puede lanzar if (Thread.currentThread().isInterrupted())
en todo el código.
Así que la incapacidad de detener a la fuerza un hilo es extraño.