En Java, un thread existe toujours dans l'un des états suivants. Ces états sont :
- Nouveau
- Actif
- Bloqué / En attente
- Attente chronométrée
- Terminé
Explication des différents états de thread
Nouveau: Chaque fois qu'un nouveau thread est créé, il est toujours dans le nouvel état. Pour un thread dans le nouvel état, le code n'a pas encore été exécuté et n'a donc pas commencé son exécution.
Actif: Lorsqu'un thread invoque la méthode start(), il passe du nouvel état à l'état actif. L'état actif contient deux états : l'un est exécutable , et l'autre est en cours d'exécution .
Un programme implémentant le multithreading acquiert une tranche de temps fixe pour chaque thread individuel. Chaque thread s'exécute pendant une courte période et lorsque cette tranche de temps allouée est terminée, le thread cède volontairement le processeur à l'autre thread, afin que les autres threads puissent également s'exécuter pendant leur tranche de temps. Chaque fois qu'un tel scénario se produit, tous les threads prêts à s'exécuter, attendant leur tour de s'exécuter, se trouvent dans l'état exécutable. Dans l'état exécutable, il existe une file d'attente où se trouvent les threads.
Bloqué ou en attente : Chaque fois qu'un thread est inactif pendant un certain temps (pas de façon permanente), soit le thread est dans l'état bloqué, soit dans l'état d'attente.
Par exemple, un thread (disons que son nom est A) peut vouloir imprimer certaines données à partir de l'imprimante. Cependant, en même temps, l'autre thread (disons que son nom est B) utilise l'imprimante pour imprimer certaines données. Par conséquent, le thread A doit attendre que le thread B utilise l’imprimante. Ainsi, le thread A est dans l’état bloqué. Un thread à l'état bloqué est incapable d'effectuer une quelconque exécution et ne consomme donc jamais aucun cycle de l'unité centrale de traitement (CPU). Par conséquent, nous pouvons dire que le thread A reste inactif jusqu'à ce que le planificateur de threads réactive le thread A, qui est en attente ou bloqué.
Lorsque le thread principal invoque alors la méthode join(), on dit que le thread principal est en état d'attente. Le thread principal attend ensuite que les threads enfants terminent leurs tâches. Lorsque les threads enfants terminent leur travail, une notification est envoyée au thread principal, qui fait à nouveau passer le thread de l'état d'attente à l'état actif.
S'il y a beaucoup de threads en attente ou bloqués, il est alors du devoir du planificateur de threads de déterminer quel thread choisir et lequel rejeter, et le thread choisi a alors la possibilité de s'exécuter.
Attente chronométrée : Parfois, attendre mène à la famine. Par exemple, un fil de discussion (son nom est A) est entré dans la section critique d'un code et ne souhaite pas quitter cette section critique. Dans un tel scénario, un autre thread (son nom est B) doit attendre indéfiniment, ce qui conduit à la famine. Pour éviter un tel scénario, un état d'attente temporisé est donné au thread B. Ainsi, le thread se trouve dans l'état d'attente pendant une période de temps spécifique, et non pour toujours. Un véritable exemple d’attente chronométrée est lorsque nous invoquons la méthode sleep() sur un thread spécifique. La méthode sleep() met le thread dans un état d'attente chronométré. Une fois le temps écoulé, le thread se réveille et commence son exécution à partir du moment où il l'a quitté plus tôt.
Terminé : Un thread atteint l'état de fin pour les raisons suivantes :
- Lorsqu'un thread a terminé son travail, il existe ou se termine normalement.
Un thread terminé signifie que le thread n'est plus dans le système. En d’autres termes, le thread est mort et il n’y a aucun moyen de réapparaître (actif après la destruction) le thread mort.
Le diagramme suivant montre les différents états impliqués dans le cycle de vie d'un thread.
Implémentation des états de thread
En Java, on peut obtenir l'état actuel d'un thread en utilisant le Thread.getState() méthode. Le java.lang.Thread.State La classe Java fournit les constantes ENUM pour représenter l'état d'un thread. Ces constantes sont :
liste.tri java
public static final Thread.State NEW
Il représente le premier état d'un thread qui est l'état NEW.
public static final Thread.State RUNNABLE
Il représente l'état exécutable. Cela signifie qu'un thread attend dans la file d'attente pour s'exécuter.
public static final Thread.State BLOCKED
Il représente l'état bloqué. Dans cet état, le thread attend d’acquérir un verrou.
public static final Thread.State WAITING
Il représente l'état d'attente. Un thread passera à cet état lorsqu'il invoquera la méthode Object.wait() ou la méthode Thread.join() sans délai d'attente. Un thread en attente attend qu’un autre thread termine sa tâche.
public static final Thread.State TIMED_WAITING
Il représente l'état d'attente chronométré. La principale différence entre l'attente et l'attente chronométrée est la contrainte de temps. L'attente n'a pas de contrainte de temps, alors que l'attente chronométrée a une contrainte de temps. Un thread appelant la méthode suivante atteint l’état d’attente chronométré.
- dormir
- rejoindre avec délai d'attente
- attendre avec délai d'attente
- se garerJusqu'à
- parcNanos
public static final Thread.State TERMINATED
Il représente l'état final d'un thread terminé ou mort. Un thread terminé signifie qu'il a terminé son exécution.
Programme Java pour démontrer les états des threads
Le programme Java suivant montre certains des états d'un thread défini ci-dessus.
Nom de fichier: 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()); } }
Sortir:
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
Explication: Chaque fois que nous générons un nouveau thread, ce thread atteint le nouvel état. Lorsque la méthode start() est invoquée sur un thread, le planificateur de thread déplace ce thread vers l'état exécutable. Chaque fois que la méthode join() est invoquée sur une instance de thread, le thread actuel exécutant cette instruction doit attendre que ce thread termine son exécution, c'est-à-dire déplacer ce thread vers l'état terminé. Par conséquent, avant que l'instruction d'impression finale ne soit imprimée sur la console, le programme invoque la méthode join() sur le thread t2, faisant attendre le thread t1 pendant que le thread t2 termine son exécution et ainsi, le thread t2 passe à l'état terminé ou mort. . Le thread t1 passe à l'état d'attente car il attend que le thread t2 termine son exécution car il a invoqué la méthode join() sur le thread t2.