java multithreading blackberry java-me

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();

De los documentos de la API

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 .