CodeGym /Blog Java /Random-ES /Multihilo: Qué hacen los métodos de la clase Thread
Autor
Pavlo Plynko
Java Developer at CodeGym

Multihilo: Qué hacen los métodos de la clase Thread

Publicado en el grupo Random-ES
¡Hola! Hoy continuaremos hablando de subprocesos múltiples. Examinemos la clase Thread y lo que hacen algunos de sus métodos. Cuando estudiamos los métodos de clase anteriormente, generalmente solo escribimos esto: <nombre del método> -> <qué hace el método>. Multithreading: Qué hacen los métodos de la clase Thread - 1Esto no funcionará con Threadlos métodos de :) Tienen una lógica más compleja que no podrás descifrar sin algunos ejemplos.

El método Thread.start()

Empecemos por repetirnos. Como probablemente recuerde, puede crear un hilo haciendo que su clase herede la Threadclase y anulando el run()método. Pero no se iniciará solo, por supuesto. Para hacer esto, llamamos al start()método de nuestro objeto. Multithreading: Qué hacen los métodos de la clase Thread - 2Recordemos el ejemplo de la lección anterior:

public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Thread executed: " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Nota: ¡ Para iniciar un hilo, debe llamar alstart()método especial en lugar delrun()método! Este es un error fácil de cometer, especialmente cuando comienzas a estudiar subprocesos múltiples. En nuestro ejemplo, si llama alrun()método 10 veces en lugar destart(), obtendría esto:

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Mire los resultados de nuestro programa: Hilo ejecutado: Hilo-0 Hilo ejecutado: Hilo-1 Hilo ejecutado: Hilo-2 Hilo ejecutado: Hilo-3 Hilo ejecutado: Hilo-4 Hilo ejecutado: Hilo-5 Hilo ejecutado: Hilo-6 Subproceso ejecutado: Subproceso-7 Subproceso ejecutado: Subproceso-8 Subproceso ejecutado: Subproceso-9 Mire el orden de la salida: Todo sucede en perfecto orden. Raro, ¿eh? No estamos acostumbrados a esto, porque ya sabemos que el orden en que se inician y ejecutan los hilos está determinado por un intelecto superior dentro de nuestro sistema operativo: el programador de hilos. ¿Tal vez solo tuvimos suerte? Por supuesto, esto no se trata de suerte. Puede verificar esto ejecutando el programa un par de veces más. El tema es que llamen alrun()El método directamente no tiene nada que ver con subprocesos múltiples. En este caso, el programa se ejecutará en el hilo principal, el mismo hilo que ejecuta el main()método. Simplemente imprime sucesivamente 10 líneas en la consola y listo. 10 hilos no han sido iniciados. Entonces, recuerda esto en el futuro y revísate constantemente. Si desea run()que se llame al método, llame a start(). Vayamos más lejos.

El método Thread.sleep()

Para suspender la ejecución del hilo actual por un tiempo, usamos el sleep()método. Multithreading: Qué hacen los métodos de la clase Thread - 3El sleep()método toma una cantidad de milisegundos como argumento, lo que indica la cantidad de tiempo para poner el subproceso en suspensión.

public class Main {

   public static void main(String[] args) throws InterruptedException {

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - How long did I sleep? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " seconds");

   }
}
Salida de la consola: - ¿Cuánto tiempo dormí? - 3 segundos Nota: el sleep()método es estático: duerme el hilo actual. Es decir, el que se está ejecutando actualmente. Aquí hay otro punto importante: un hilo durmiente puede ser interrumpido. En este caso, el programa lanza un InterruptedException. Consideraremos un ejemplo a continuación. Por cierto, ¿qué sucede después de que el hilo se despierta? ¿Continuará ejecutándose justo donde lo dejó? No. Después de que un subproceso se despierta, es decir, el tiempo pasado como argumento ha Thread.sleep()pasado, pasa a ser ejecutable.estado. Pero esto no significa que el programador de subprocesos lo ejecutará. Es muy posible que dé preferencia a algún otro subproceso que no esté dormido y permita que nuestro subproceso recién despertado continúe su trabajo un poco más tarde. Asegúrese de recordar esto: ¡despertarse no significa continuar trabajando inmediatamente!

El método Thread.join()

Multithreading: Qué hacen los métodos de la clase Thread - 4El join()método suspende la ejecución del subproceso actual hasta que finalice otro subproceso. Si tenemos 2 hilos, t1y t2, y escribimos

t1.join()
entonces t2no comenzará hasta que t1haya terminado su trabajo. El join()método se puede utilizar para garantizar el orden de ejecución de los hilos. Consideremos cómo join()funciona el método en el siguiente ejemplo:

public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Thread started: " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Thread " + getName() + " is finished.");
   }
}


public class Main {

   public static void main(String[] args) throws InterruptedException {

       ThreadExample t1 = new ThreadExample();
       ThreadExample t2 = new ThreadExample();

       t1.start();


 /* The second thread (t2) will start running only after the first thread (t1)
       is finished (or an exception is thrown) */
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       // The main thread will continue running only after t1 and t2 have finished
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("All threads have finished. The program is finished.");

   }
}
Creamos una ThreadExampleclase simple. Su tarea es mostrar un mensaje de que el hilo ha comenzado, quedarse dormido durante 5 segundos y finalmente informar que el trabajo está completo. Pedazo de pastel. La lógica principal está en la Mainclase. Mire los comentarios: usamos el join()método para administrar con éxito el orden de ejecución de los hilos. Si recuerda cómo comenzamos este tema, el programador de subprocesos maneja el orden de ejecución. Ejecuta subprocesos a su propia discreción: cada vez de una manera diferente. Aquí estamos usando el método para garantizar que el t1subproceso se iniciará y ejecutará primero, luego elt2hilo, y solo después de eso continuará el hilo principal del programa. Hacia adelante. En programas reales, a menudo encontrará situaciones en las que necesitará interrumpir la ejecución de un hilo. Por ejemplo, nuestro subproceso se está ejecutando, pero está esperando un determinado evento o condición. Si ocurre, entonces el hilo se detiene. Probablemente tendría sentido si hubiera algún tipo de stop()método. Pero no es tan simple. Érase una vez, Java realmente tenía un Thread.stop()método y permitía que se interrumpiera un hilo. Pero luego se eliminó de la biblioteca de Java. Puede encontrarlo en la documentación de Oracle y ver que está marcado como obsoleto. ¿Por qué? Porque simplemente detuvo el hilo sin hacer nada más. Por ejemplo, el subproceso podría estar trabajando con datos y cambiando algo. Luego, en medio de su trabajo, fue abruptamente y sin ceremonias cortado por el stop()método. Sin un apagado adecuado, ni la liberación de recursos, ni siquiera el manejo de errores, no había nada de esto. Para exagerar un poco, el stop()método simplemente destruyó todo a su paso. Era como sacar el cable de alimentación del tomacorriente para apagar la computadora. Sí, puedes obtener el resultado deseado. Pero todo el mundo sabe que después de un par de semanas la computadora no te agradecerá por tratarla de esa manera. Es por eso que la lógica para interrumpir hilos cambió en Java y ahora usa un interrupt()método especial.

El método Thread.interrupt()

¿Qué sucede si interrupt()se llama al método en un hilo? Hay 2 posibilidades:
  1. Si el objeto estaba en estado de espera, por ejemplo, debido a los métodos joino sleep, la espera se interrumpirá y el programa arrojará un InterruptedException.
  2. Si el subproceso estaba en un estado de funcionamiento, la interruptedbandera booleana se establecerá en el objeto.
¡Pero tenemos que verificar el valor de esta bandera en el objeto y completar correctamente el trabajo por nuestra cuenta! Es por eso que la Threadclase tiene el boolean isInterrupted()método. Volvamos al ejemplo del reloj que estaba en una lección del curso básico. Para mayor comodidad, lo hemos simplificado ligeramente:

public class Clock extends Thread {

   public static void main(String[] args) throws InterruptedException {
       Clock clock = new Clock();
       clock.start();

       Thread.sleep(10000);
       clock.interrupt();
   }

   public void run() {
       Thread current = Thread.currentThread();

       while (!current.isInterrupted())
       {
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               System.out.println("The thread was interrupted");
               break;
           }
           System.out.println("Tick");
       }
   }
}
En este caso, el reloj se pone en marcha y empieza a correr cada segundo. En el décimo segundo, interrumpimos el hilo del reloj. Como ya sabes, si el hilo que estamos tratando de interrumpir está en uno de los estados de espera, el resultado es un archivo InterruptedException. Esta es una excepción comprobada, por lo que podemos detectarla fácilmente y ejecutar nuestra lógica para finalizar el programa. Y eso es justo lo que hicimos. Aquí está nuestro resultado: Tick Tick Tick Tcik Tick Tick Tick Tick Tick El hilo fue interrumpido Esto concluye nuestra introducción a los Threadmétodos más importantes de la clase. ¡Buena suerte!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION