A veces es útil suspender la ejecución de un hilo. Por ejemplo, un hilo separado se puede usar para mostrar la hora del día. Si el usuario no desea un reloj, entonces su hilo puede ser suspendido.
En cualquier caso, es una cuestión simple suspender un hilo. Una vez suspendido, también es una cuestión simple reiniciar el hilo.
Los mecanismos para suspender, detener y reanudar los hilos difieren entre las primeras versiones de Java y las versiones más modernas, comenzando con Java 2. Antes de Java 2, un programa usa suspend(), resume() y stop(), que son métodos definido por Thread, pausar, reiniciar y detener la ejecución de un hilo. Ellos tienen las siguientes formas:
final void resume( )
final void suspend( )
final void stop( )
Si bien estos métodos parecen ser un enfoque perfectamente razonable y conveniente para gestionar la ejecución de los hilos, ya no se deben usar. Esto es el por qué. El método suspend() de la clase Thread fue desaprobado por Java 2. Esto se hizo porque suspend() a veces puede causar serios problemas que involucran bloqueos.
El método resume() también está en desuso. No causa problemas pero no puede usarse sin el método suspend() como contraparte.
El método stop() de la clase Thread también fue desaprobado por Java 2. Esto se hizo porque este método también a veces puede causar problemas graves.
Dado que ahora no puede usar los métodos suspend(), resume() o stop() para controlar un hilo, al principio podría pensar que no hay forma de pausar, reiniciar o terminar un hilo. Pero, afortunadamente, esto no es verdad.
En su lugar, un hilo debe diseñarse de modo que el método run() compruebe periódicamente para determinar si ese hilo debe suspender, reanudar o detener su propia ejecución.
Normalmente, esto se logra estableciendo dos variables de indicador: una para suspender y reanudar, y otra para detener. Para suspender y reanudar, siempre que el indicador esté configurado como en “running”, el método run() debe continuar permitiendo que el hilo se ejecute.
Si esta variable está configurada en “stop”, el hilo debe detenerse. Para el indicador de detención, si está configurado para “stop”, el hilo debe terminar.
El siguiente ejemplo muestra una forma de implementar tus propias versiones de suspend(), resume() y stop():
//Ejemplo para suspender, pausar y reanudar un Hilo
class MiHilo implements Runnable{
Thread hilo;
boolean suspender; //Suspende un hilo cuando es true
boolean pausar; //Detiene un hilo cuando es true
MiHilo (String nombre){
hilo=new Thread(this,nombre);
suspender=false;
pausar=false;
}
public static MiHilo crearEIniciar(String nombre){
MiHilo miHilo=new MiHilo(nombre);
miHilo.hilo.start(); //Iniciar el hilo
return miHilo;
}
public void run() {
System.out.println(hilo.getName()+ " iniciando.");
try {
for (int i=1;i<1000;i++){
System.out.print(i+" ");
if ((i%10)==0){
System.out.println();
Thread.sleep(250);
}
synchronized (this) {
while (suspender) {
wait();
}
if (pausar) break;
}
}
}catch (InterruptedException exc){
System.out.println(hilo.getName()+ "interrumpido.");
}
System.out.println(hilo.getName()+ " finalizado.");
}
//Pausar el hilo
synchronized void pausarhilo(){
pausar=true;
//lo siguiente garantiza que un hilo suspendido puede detenerse.
suspender=false;
notify();
}
//Suspender un hilo
synchronized void suspenderhilo(){
suspender=true;
}
//Renaudar un hilo
synchronized void renaudarhilo(){
suspender=false;
notify();
}
}
class Suspender {
public static void main(String[] args) {
MiHilo mh1=MiHilo.crearEIniciar("Mi Hilo");
try {
Thread.sleep(1000);//dejar que el primer hilo comience a ejecutarse
mh1.suspenderhilo();
System.out.println("Suspendiendo Hilo.");
Thread.sleep(1000);
mh1.renaudarhilo();
System.out.println("Renaudando Hilo.");
Thread.sleep(1000);
mh1.suspenderhilo();
System.out.println("Suspendiendo Hilo.");
Thread.sleep(1000);
mh1.renaudarhilo();
System.out.println("Renaudando Hilo.");
Thread.sleep(1000);
mh1.suspenderhilo();
System.out.println("Pausando Hilo.");
mh1.pausarhilo();
}catch (InterruptedException e){
System.out.println("Hilo principal interrumpido.");
}
//esperar a que el hilo termine
try {
mh1.hilo.join();
}catch (InterruptedException e){
System.out.println("Hilo principal interrumpido.");
}
System.out.println("Hilo principal finalizado.");
}
}
Se muestra la salida de este programa a continuación. (Su salida puede diferir ligeramente).
Mi Hilo iniciando.
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
Suspendiendo Hilo.
Renaudando Hilo.
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
Suspendiendo Hilo.
Renaudando Hilo.
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
Pausando Hilo.
Mi Hilo finalizado.
Hilo principal finalizado.
Así es como funciona el programa. La clase MiHilo define dos variables booleanas, suspender y pausar, que rigen la suspensión y la terminación de un hilo. Ambos son inicializadas como false por el constructor.
El método run() contiene un bloque de instrucción sincronizado (synchronized) que verifica la suspensión. Si esa variable es true, se invoca el método wait() para suspender la ejecución del hilo. Para suspender la ejecución del hilo, llame a suspenderhilo(), que establece suspender en true.
Para reanudar la ejecución, llame renaudarhilo(), que establece suspender a false e invoca notify() para reiniciar el hilo.
Finalmente, para detener el hilo, llame a pausarhilo(), que establece pausar en true. Además, pausarhilo() establece suspender en false y luego llama a notify(). Estos pasos son necesarios para detener un hilo suspendido.