logo

Ciclo de vida de un Thread (Estados del Thread)

En Java, un hilo siempre existe en cualquiera de los siguientes estados. Estos estados son:

  1. Nuevo
  2. Activo
  3. Bloqueado / Esperando
  4. Espera cronometrada
  5. Terminado

Explicación de los diferentes estados de los hilos

Nuevo: Cada vez que se crea un nuevo hilo, siempre está en el nuevo estado. Para un hilo en el estado nuevo, el código aún no se ha ejecutado y, por lo tanto, no ha comenzado su ejecución.

Activo: Cuando un hilo invoca el método start(), pasa del nuevo estado al estado activo. El estado activo contiene dos estados dentro de él: uno es ejecutable , y el otro es correr .

    Ejecutable:Un subproceso que está listo para ejecutarse se mueve al estado ejecutable. En el estado ejecutable, el subproceso puede estar ejecutándose o puede estar listo para ejecutarse en cualquier instante dado. Es deber del programador de subprocesos proporcionar el tiempo de ejecución del subproceso, es decir, mover el subproceso al estado de ejecución.
    Un programa que implementa subprocesos múltiples adquiere un período de tiempo fijo para cada subproceso individual. Todos y cada uno de los subprocesos se ejecutan durante un corto período de tiempo y cuando finaliza ese período de tiempo asignado, el subproceso cede voluntariamente la CPU al otro subproceso, para que los otros subprocesos también puedan ejecutarse durante su período de tiempo. Siempre que ocurre tal escenario, todos aquellos subprocesos que están dispuestos a ejecutarse, esperando su turno para ejecutarse, se encuentran en el estado ejecutable. En el estado ejecutable, hay una cola donde se encuentran los subprocesos.Correr:Cuando el subproceso obtiene la CPU, pasa del estado ejecutable al estado de ejecución. Generalmente, el cambio más común en el estado de un hilo es de ejecutable a ejecutable y nuevamente a ejecutable.

Bloqueado o en espera: Siempre que un subproceso está inactivo durante un período de tiempo (no permanentemente), el subproceso está en estado bloqueado o en estado de espera.

Por ejemplo, un hilo (digamos que su nombre es A) puede querer imprimir algunos datos de la impresora. Sin embargo, al mismo tiempo, el otro hilo (digamos que su nombre es B) está usando la impresora para imprimir algunos datos. Por lo tanto, el hilo A tiene que esperar a que el hilo B utilice la impresora. Por tanto, el hilo A está en estado bloqueado. Un subproceso en estado bloqueado no puede realizar ninguna ejecución y, por lo tanto, nunca consume ningún ciclo de la Unidad Central de Procesamiento (CPU). Por lo tanto, podemos decir que el subproceso A permanece inactivo hasta que el programador de subprocesos reactiva el subproceso A, que está en estado de espera o bloqueado.

Cuando el hilo principal invoca el método join(), se dice que el hilo principal está en estado de espera. Luego, el hilo principal espera a que los hilos secundarios completen sus tareas. Cuando los subprocesos secundarios completan su trabajo, se envía una notificación al subproceso principal, que nuevamente mueve el subproceso del estado de espera al estado activo.

Si hay muchos subprocesos en estado de espera o bloqueado, entonces es responsabilidad del programador de subprocesos determinar qué subproceso elegir y cuál rechazar, y luego al subproceso elegido se le da la oportunidad de ejecutarse.

Espera cronometrada: A veces, esperar lleva a morir de hambre. Por ejemplo, un hilo (su nombre es A) ha entrado en la sección crítica de un código y no está dispuesto a salir de esa sección crítica. En tal escenario, otro hilo (su nombre es B) tiene que esperar eternamente, lo que conduce a la inanición. Para evitar tal escenario, se le da un estado de espera cronometrado al subproceso B. Por lo tanto, el subproceso permanece en estado de espera durante un período de tiempo específico, y no para siempre. Un ejemplo real de espera cronometrada es cuando invocamos el método sleep() en un hilo específico. El método sleep() pone el hilo en el estado de espera cronometrada. Una vez que se acaba el tiempo, el hilo se activa y comienza su ejecución desde cuando se fue antes.

Terminado: Un hilo alcanza el estado de terminación por las siguientes razones:

  • Cuando un hilo ha terminado su trabajo, existe o termina normalmente.
  • Terminación anormal:Ocurre cuando se producen algunos eventos inusuales, como una excepción no controlada o un error de segmentación.

Un hilo terminado significa que el hilo ya no está en el sistema. En otras palabras, el hilo está muerto y no hay manera de que uno pueda reaparecer (activo después de matar) el hilo muerto.

El siguiente diagrama muestra los diferentes estados involucrados en el ciclo de vida de un hilo.

Ciclo de vida del hilo Java

Implementación de estados de subprocesos

En Java, se puede obtener el estado actual de un hilo utilizando el Hilo.getState() método. El java.lang.Thread.Estado La clase de Java proporciona las constantes ENUM para representar el estado de un hilo. Estas constantes son:

25 c a k
 public static final Thread.State NEW 

Representa el primer estado de un hilo que es el estado NUEVO.

 public static final Thread.State RUNNABLE 

Representa el estado ejecutable. Significa que un subproceso está esperando en la cola para ejecutarse.

 public static final Thread.State BLOCKED 

Representa el estado bloqueado. En este estado, el hilo está esperando adquirir un bloqueo.

 public static final Thread.State WAITING 

Representa el estado de espera. Un hilo pasará a este estado cuando invoque el método Object.wait() o el método Thread.join() sin tiempo de espera. Un hilo en estado de espera está esperando que otro hilo complete su tarea.

 public static final Thread.State TIMED_WAITING 

Representa el estado de espera cronometrado. La principal diferencia entre espera y espera cronometrada es la limitación de tiempo. La espera no tiene restricción de tiempo, mientras que la espera cronometrada sí la tiene. Un hilo que invoca el siguiente método alcanza el estado de espera cronometrado.

  • dormir
  • unirse con tiempo de espera
  • esperar con tiempo de espera
  • parqueHasta
  • parqueNanos
 public static final Thread.State TERMINATED 

Representa el estado final de un hilo que está terminado o muerto. Un hilo terminado significa que ha completado su ejecución.

Programa Java para demostrar estados de subprocesos

El siguiente programa Java muestra algunos de los estados de un hilo definido anteriormente.

Nombre del archivo: ThreadState.java

 // ABC class implements the interface Runnable class ABC implements Runnable { public void run() { // try-catch block try { // moving thread t2 to the state timed waiting Thread.sleep(100); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t1 while it invoked the method join() on thread t2 -'+ ThreadState.t1.getState()); // try-catch block try { Thread.sleep(200); } catch (InterruptedException ie) { ie.printStackTrace(); } } } // ThreadState class implements the interface Runnable public class ThreadState implements Runnable { public static Thread t1; public static ThreadState obj; // main method public static void main(String argvs[]) { // creating an object of the class ThreadState obj = new ThreadState(); t1 = new Thread(obj); // thread t1 is spawned // The thread t1 is currently in the NEW state. System.out.println('The state of thread t1 after spawning it - ' + t1.getState()); // invoking the start() method on // the thread t1 t1.start(); // thread t1 is moved to the Runnable state System.out.println('The state of thread t1 after invoking the method start() on it - ' + t1.getState()); } public void run() { ABC myObj = new ABC(); Thread t2 = new Thread(myObj); // thread t2 is created and is currently in the NEW state. System.out.println('The state of thread t2 after spawning it - '+ t2.getState()); t2.start(); // thread t2 is moved to the runnable state System.out.println('the state of thread t2 after calling the method start() on it - ' + t2.getState()); // try-catch block for the smooth flow of the program try { // moving the thread t1 to the state timed waiting Thread.sleep(200); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t2 after invoking the method sleep() on it - '+ t2.getState() ); // try-catch block for the smooth flow of the program try { // waiting for thread t2 to complete its execution t2.join(); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println('The state of thread t2 when it has completed it's execution - ' + t2.getState()); } } 

Producción:

 The state of thread t1 after spawning it - NEW The state of thread t1 after invoking the method start() on it - RUNNABLE The state of thread t2 after spawning it - NEW the state of thread t2 after calling the method start() on it - RUNNABLE The state of thread t1 while it invoked the method join() on thread t2 -TIMED_WAITING The state of thread t2 after invoking the method sleep() on it - TIMED_WAITING The state of thread t2 when it has completed it's execution - TERMINATED 

Explicación: Cada vez que generamos un nuevo hilo, ese hilo alcanza el nuevo estado. Cuando se invoca el método start() en un subproceso, el programador de subprocesos mueve ese subproceso al estado ejecutable. Siempre que se invoca el método join() en cualquier instancia de subproceso, el subproceso actual que ejecuta esa declaración tiene que esperar a que este subproceso finalice su ejecución, es decir, mover ese subproceso al estado terminado. Por lo tanto, antes de que la declaración print final se imprima en la consola, el programa invoca el método join() en el hilo t2, haciendo que el hilo t1 espere mientras el hilo t2 finaliza su ejecución y así, el hilo t2 llega al estado terminado o muerto. . El subproceso t1 pasa al estado de espera porque está esperando que el subproceso t2 finalice su ejecución ya que ha invocado el método join() en el subproceso t2.