java - Detener thread y nuevamente comenzar a dar IllegalThreadStateException en blackberry
multithreading java-me (2)
IllegalThreadStateException
excepción IllegalThreadStateException
cuando uso el siguiente código: ya he comenzado este subproceso una vez (usando thread.start()
) y de nuevo tratando de iniciarlo en otro lugar, así que utilicé el siguiente código:
thread.interrupt();
thread.start();
Pero thread.start()
está lanzando IllegalThreadStateException
.
¿Qué debería usar para resolverlo?
Thread
objetos de Thread
solo deben comenzarse una vez. Si necesita detener / interrumpir un Thread
y luego desea volver a iniciarlo, debe crear una nueva instancia y llamar a start()
en él:
thread.interrupt(); // if you need to make sure thread''s run() method stops ASAP
thread = new MyThreadSubclass();
thread.start();
IllegalThreadStateException : si el hilo ya se inició.
Sé que no está 100% claro que no puede start()
llamar a start()
, incluso si llamó previamente a interrupt()
, pero así es como funciona.
Si mira los documentos API para Java estándar , este problema es más claro.
Además de la respuesta de Nate.
AnkitRox afirma en su comentario:
Gracias Nate. También estaba probando tu método. Pero el problema que ocurrió en ese momento fue que se inició un nuevo hilo para la nueva instancia y el hilo anterior también estaba funcionando.
Por lo tanto, parece que el problema es "el hilo aún se está ejecutando, incluso si llamé a la interrupción" . Considere esta muestra (es fea, pero suficiente para mostrar la idea principal):
final Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
for (int i = 0; i < 100000000; i++); // simulate some action
System.out.println("hi, interrupted = "
+ Thread.currentThread().isInterrupted());
}
}
});
t.start();
new Timer(true).schedule(
new TimerTask() {
public void run() {
t.interrupt();
}
},
1000 // 1 second delay
);
Tenga en cuenta que el hilo continúa ejecutándose incluso después de haber llamado a interrupt()
. El resultado producido es:
hi, interrupted = false
hi, interrupted = true
hi, interrupted = true
hi, interrupted = true
...
hi, interrupted = true
En realidad, el programa nunca se detiene a menos que se cierre con fuerza. Entonces, ¿qué hace la interrupt()
? Simplemente establece el indicador interrumpido en true
. Después de que interrupt()
se ha llamado Thread.currentThread().isInterrupted()
comienza a devolver false
. Y eso es todo.
Otro caso es si se invoca interrupt()
mientras el hilo está bloqueado en una invocación de uno de los métodos que lanzan InterruptedException
, luego ese método devolverá lanzando la InterruptedException
. Y si el código del hilo simplemente "come" esa excepción, entonces el hilo seguirá ejecutándose, considere una muestra:
final Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("hi, interrupted = "
+ Thread.currentThread().isInterrupted());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("got InterruptedException");
}
}
}
});
t.start();
new Timer(true).schedule(
new TimerTask() {
public void run() {
t.interrupt();
}
},
1000 // 1 second delay
);
Tenga en cuenta que el hilo continúa ejecutándose incluso después de haber llamado a interrupt()
. El resultado producido es:
hi, interrupted = false
got InterruptedException
hi, interrupted = false
hi, interrupted = false
...
hi, interrupted = false
Tenga en cuenta que esta vez interrupted = false
incluso después de que se ha llamado a interrupt()
. Esto se debe a que cuando se InterruptedException
, el indicador interrumpido se restablece a false
.
En Java detener un hilo es un mecanismo cooperativo . Lo que significa que no se puede hacer sin la cooperación del hilo en sí. Aquí está la versión fija de la muestra anterior:
final Thread t = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("hi, interrupted = "
+ Thread.currentThread().isInterrupted());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("we''ve been interrupted");
// restore the interrupted flag
Thread.currentThread().interrupt();
}
}
}
});
t.start();
new Timer(true).schedule(
new TimerTask() {
public void run() {
t.interrupt();
}
},
1000 // 1 second delay
);
Entonces, el enfoque correcto debería ser verificar periódicamente el indicador interrumpido . Y si se detecta el estado interrumpido, solo devuelva lo antes posible. Otra opción común es no utilizar Thread.interrupt()
en absoluto, sino algunos booleanos personalizados en su lugar .