JavaRush /Blog Java /Random-ES /Subprocesos múltiples: qué hacen los métodos de clase de ...

Subprocesos múltiples: qué hacen los métodos de clase de subprocesos

Publicado en el grupo Random-ES
¡Hola! Hoy seguimos hablando de subprocesos múltiples. Echemos un vistazo a la clase Thread y cómo funcionan sus distintos métodos. Anteriormente, cuando estudiábamos métodos de clase, la mayoría de las veces simplemente lo escribíamos así: "nombre del método" -> "qué hace".
Multithreading: que hacen los métodos de la clase Thread - 1
Esto no funcionará con los métodos Thread :) Su lógica es más complicada y sin varios ejemplos es imposible de entender.

Método thread.start()

Empecemos por la repetición. Como probablemente recuerdes, puedes crear un hilo heredando tu clase de la clase Thready anulando el método en él run(). Pero, por supuesto, no empezará por sí solo. Para hacer esto, llamamos al método en nuestro objeto start(). Multithreading: que hacen los métodos de la clase Thread - 2Recordemos el ejemplo de la conferencia anterior:
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Выполнен поток " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Tenga en cuenta: para iniciar un hilo, debe llamar al método especialstart(), no al métodorun()! Este es un error fácil de cometer, especialmente cuando se aprende multiproceso por primera vez. Si en nuestro ejemplo llamas a un método en un objeto 10 vecesrun()en lugar destart(), el resultado será así:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
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 hilo ejecutado Hilo-7 hilo ejecutado Hilo-8 hilo ejecutado Hilo-9 hilo ejecutado Mire la secuencia de salida: todo va estrictamente en orden. Extraño, ¿verdad? No estamos acostumbrados a esto, porque ya sabemos que el orden en que se inician y ejecutan los subprocesos está determinado por la superinteligencia dentro de nuestro sistema operativo: el programador de subprocesos. ¿Quizás simplemente tuve suerte? Por supuesto, no es cuestión de suerte. Puedes verificar esto ejecutando el programa un par de veces más. El punto es que llamar a un método directamenterun()no tiene nada que ver con el subproceso múltiple. En este caso, el programa se ejecutará en el hilo principal, aquel en el que se ejecuta el métodomain(). Simplemente enviará 10 líneas secuencialmente a la consola y listo. No se iniciarán 10 hilos. Por lo tanto, recuerde para el futuro y compruébelo constantemente. Si quieres que se hagarun(), llámalostart(). Vamonos.

Método thread.sleep()

Para pausar la ejecución del hilo actual durante algún tiempo, utilice el archivo sleep(). Multithreading: que hacen los métodos de la clase Thread - 3El método sleep()toma como parámetro el número de milisegundos, es decir, el tiempo durante el cual se debe poner el hilo en suspensión.
public class Main {

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

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - Сколько я проспал? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " секунды");

   }
}
Salida de la consola: - ¿Cuánto tiempo dormí? - 3 segundos Tenga en cuenta: el método sleep()es estático: pone el hilo actual en suspensión. Es decir, el que está funcionando en estos momentos. Otro matiz importante: el flujo en estado de sueño puede interrumpirse. En este caso, se producirá una excepción en el programa InterruptedException. Veremos un ejemplo a continuación. Por cierto, ¿qué pasa después de que el hilo "se despierta"? ¿Continuará inmediatamente su ejecución desde donde la dejó? No. Después de que el hilo se activa (cuando expira el tiempo transcurrido como argumento Thread.sleep()), entra en el estado ejecutable . Sin embargo, esto no significa que el programador de subprocesos lo ejecutará. Es muy posible que dé preferencia a algún otro hilo "no dormido", y nuestro hilo "recién despierto" seguirá funcionando un poco más tarde. Asegúrate de recordar: “¡despertar no significa seguir trabajando en ese mismo segundo!”

Método thread.join()

Multithreading: que hacen los métodos de la clase Thread - 4El método join()suspende la ejecución del hilo actual hasta que se complete otro hilo. Si tenemos 2 hilos, t1y t2y escribimos -
t1.join()
t2no comenzará a funcionar hasta que t1 haya completado su trabajo. El método join()se puede utilizar para garantizar la secuencia de ejecución de los subprocesos. Veamos el trabajo join()con un ejemplo:
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Начало работы потока " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Поток " + getName() +  " завершил работу.");
   }
}


public class Main {

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

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

       t1.start();


 /*Второй поток t2 начнет выполнение только после того, Cómo будет завершен
       (o бросит исключение) первый поток - t1*/
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       //Главный поток продолжит работу только после того, Cómo t1 и t2 завершат работу
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("Все потоки закончo работу, программа завершена");

   }
}
Hemos creado una clase sencilla ThreadExample. Su tarea es mostrar un mensaje en la pantalla sobre el inicio del trabajo, luego quedarse dormido durante 5 segundos y al final informar sobre la finalización del trabajo. Nada complicado. La lógica principal está contenida en la clase Main. Mire los comentarios: utilizando el método, join()controlamos con éxito la secuencia de ejecución de los subprocesos. Si recuerdas el comienzo del tema, el programador de hilos hizo esto. Los lanzó a su discreción: cada vez de forma diferente. Aquí, usando el método, nos aseguramos de que primero se iniciara y ejecutara el hilo t1, luego el hilo t2, y solo después de ellos el hilo principal de ejecución del programa. Adelante. En programas reales, a menudo encontrará situaciones en las que necesitará interrumpir la ejecución de algún hilo. Por ejemplo, nuestro hilo se está ejecutando, pero está esperando que se cumpla un determinado evento o condición. Si esto sucede, se detiene. Probablemente sería lógico si existiera algún método como stop(). Sin embargo, no todo es tan sencillo. Érase una vez un método Thread.stop()en Java que permitía interrumpir el trabajo de un hilo. Pero luego fue eliminado de la biblioteca Java. Puede buscarlo en la documentación de Oracle y ver que está marcado como obsoleto . ¿Por qué? Porque simplemente detuvo el flujo sin ningún trabajo adicional. Por ejemplo, un hilo podría trabajar con datos y cambiar algo en ellos. Luego, de repente, en medio del trabajo lo noquearon stop()y eso fue todo. No hubo un cierre correcto, ni liberación de recursos, ni siquiera manejo de errores; nada de esto sucedió. El método stop(), para exagerar, simplemente destruyó todo a su paso. Su funcionamiento se puede comparar con cómo alguien desconecta el enchufe del enchufe para apagar una computadora. Sí, puedes lograr el resultado deseado. Pero todo el mundo entiende que en un par de semanas la computadora no dirá "gracias" por esto. Por esta razón, se cambió la lógica para interrumpir subprocesos en Java y ahora se utiliza un método especial: interrupt().

Método thread.interrupt()

¿Qué sucede si llamas a un método interrupt() en un hilo ? Hay 2 opciones:
  1. Si el objeto estaba en estado de espera en ese momento, por ejemplo, joino sleep, la espera se interrumpirá y el programa arrojará InterruptedException.
  2. Si el hilo estaba en estado de funcionamiento en ese momento, se establecerá el indicador booleano del objeto interrupted.
¡Pero tendremos que verificar el valor de esta bandera en el objeto y completar el trabajo correctamente nosotros mismos! Para ello, la clase Threadtiene un método especial: boolean isInterrupted(). Volvamos al ejemplo del reloj de la conferencia principal. Por conveniencia, está ligeramente simplificado:
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("Работа потока была прервана");
               break;
           }
           System.out.println("Tik");
       }
   }
}
En nuestro caso, el reloj arranca y empieza a correr cada segundo. En el décimo segundo interrumpimos el flujo del reloj. Como ya sabes, si el hilo que intentamos interrumpir está en uno de los estados de espera, esto resulta en InterruptedException. Este tipo de excepción es una excepción comprobada, por lo que puede detectarse fácilmente y ejecutarse la lógica de terminación de nuestro programa. Eso es lo que hicimos. Aquí está nuestro resultado: Tik Tik Tik Tik Tik Tik Tik Tik Tik El trabajo del hilo fue interrumpido, con esto concluye nuestra introducción a los principales métodos de la clase Thread. Para consolidar sus conocimientos, puede ver esta videoconferencia sobre subprocesos múltiples:
¡Te servirá como excelente material adicional! Al final, después de una descripción general de los métodos, dice exactamente lo que veremos a continuación en el curso :) ¡Buena suerte!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION