java - saber - Cómo detener un hilo que se está ejecutando para siempre sin ningún uso
hilos en java netbeans (6)
Cree un campo boolean keepGoing
que establezca en true
antes de iniciar su hilo y reemplace while (true)
con while (keepGoing)
. En algún momento, usted decide dónde, simplemente cambie el valor de keepGoing
a false
y saldrá del bucle.
En el siguiente código, tengo un bucle while (verdadero). considerando una situación en la que hay algo de código en el bloque de prueba donde se supone que el subproceso debe realizar algunas tareas que demoran aproximadamente un minuto, pero debido a algún problema esperado, se está ejecutando para siempre. podemos detener ese hilo?
public class thread1 implements Runnable {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
thread1 t1 = new thread1();
t1.run();
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try{
Thread.sleep(10);
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
En primer lugar, no estás empezando ningún hilo aquí! Debe crear un nuevo hilo y pasarle el nombre confuso de thread1
Runnable
:
thread1 t1 = new thread1();
final Thread thread = new Thread(t1);
thread.start();
Ahora, cuando realmente tienes un hilo, hay una función incorporada para interrumpir los hilos en ejecución, llamada ... interrupt()
:
thread.interrupt();
Sin embargo, la configuración de este indicador solo no hace nada, tiene que manejar esto en su hilo en ejecución:
while(!Thread.currentThread().isInterrupted()){
try{
Thread.sleep(10);
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
break; //optional, since the while loop conditional should detect the interrupted state
}
catch(Exception e){
e.printStackTrace();
}
Dos cosas a tener en cuenta: while
bucle ahora terminará cuando el hilo sea isInterrupted()
. Pero si el hilo se interrumpe durante el modo de espera, JVM es tan amable que le informará sobre cómo lanzar InterruptedException
fuera de estado de sleep()
. Atrapalo y rompe tu bucle. ¡Eso es!
En cuanto a otras sugerencias:
- Acerca de Thread.stop() :
En desuso Este método es inherentemente inseguro [...]
- Está bien agregar su propia bandera y
AtomicBoolean
(¡recuerde usarAtomicBoolean
ovolatile
!), Pero ¿por qué molestarse si JDK ya le proporciona una bandera incorporada como esta? El beneficio adicional es la interrupción delsleep
, lo que hace que la interrupción del hilo sea más receptiva.
La única forma de detener un hilo arbitrario es interrumpiéndolo . Mantenga una referencia a él y luego llame al método de interrupción.
La forma correcta de detener un hilo es interrupt
( stop()
está en desuso y puede tener efectos secundarios desagradables):
t1.interrupt()
Esto provocará que se Thread.sleep()
una InterruptedException
mediante métodos como Thread.sleep()
o Object.wait()
.
Luego solo agregue un bloque catch para esta excepción y simplemente salga del bucle while.
EDITAR: Ahora me di cuenta de que su bucle infinito se está ejecutando dentro del hilo principal, no hay ningún hilo creado por su código, simplemente se run()
un Runnable
. Thread.start()
llamar a Thread.start()
en algún punto para generar un nuevo hilo.
Mueva la interrupción de captura fuera del bucle. Esto no requiere más líneas de código, solo maneja las interrupciones correctamente, es decir, la acción se interrumpe.
public void run() {
try{
while(true) {
Thread.sleep(10);
}
} catch(InterruptedException e){
System.out.println("Thread interrupted"));
}
}
Recomiendo usar Thread.interrupt()
(como lo menciona @Bohemian). Tiene un par de ventajas sobre el uso de banderas ad-hoc :
No es necesario crear y usar una API específica de la aplicación para hacer esto. (Y las interrupciones están garantizadas sin hilos ...)
Thread.interrupt()
interrumpirá los subprocesos que están bloqueados en unwait()
o en unajoin
, o posiblemente en algunas llamadas de E / S de bloqueo.
Sin embargo, no es una bala mágica. Si el subproceso que está intentando detener está ejecutando un código normal, debe verificar periódicamente su interrupted()
, o no dejar de hacerlo. Esto nos deja en el mismo barco que con un mecanismo de bandera ad-hoc . El hilo debe cooperar o no se puede detener (de forma segura).
1 - Esta es una zona oscura. Por un lado, hay una InterruptedIOException
cuyo javadoc dice "Señala que se ha interrumpido una operación de E / S" . Por otro lado, la excepción no se menciona explícitamente en los javadocs para las diversas clases de flujo de java.io.
Es cierto que es posible que algunos códigos de terceros no se ocupen de la señalización interrupted
correctamente y que las interrupciones se "coman" como resultado. Pero puedes verificarlo si tienes código fuente. Y la situación no es muy diferente al código de terceros que no presta atención a su mecanismo de marca ad-hoc .
NO recomendaría el uso de Thread.stop()
. Es fundamentalmente flakey. Algunas personas afirman que les funciona, pero en mi opinión, están tratando un caso especial que funciona ... o están teniendo suerte.