US

États d'un thread

Durant le cours de sa vie, un thread va se trouver dans différents états. En fonction de son état, certaines opérations seront possibles ou non. Il est donc important de bien connaitre ces différents états et de savoir quand est-ce-qu'un thread change d'état. La figure suivante reprend les cinq états principaux possibles.

Les états d'un thread
Figure 1.4 Les états d'un thread.

Cette section va passer en revue les différents états possibles d'un thread, mais avant cela, voyons une méthode d'instance de la classe Thread qui permet de connaitre l'état courant d'un thread.

public Thread.State getState();

La méthode renvoie un résultat de type Thread.State. Il s'agit d'une énumération qui comporte six valeurs différentes correspondant aux états d'un thread : NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING et TERMINATED. Vous pouvez voir que ces valeurs ne correspondent pas exactement aux états présentés sur la figure 1. Nous ferons le lien entre ceux-ci au fur et à mesure qu'on va décrire les états de la figure 1.

Création

Lorsqu'on crée l'objet Thread, celui-ci se trouve dans l'état New. Il n'y a en fait pas encore de ressources allouées au thread, seul l'objet Thread a été créé dans le tas. Dans cet état, la seule chose à faire est d'appeler la méthode start afin de créer le thread et de le démarrer. Cet état correspond à la valeur NEW de l'énumération Thread.State.

En cours d'exécution

Une fois la méthode start appelée, le thread se trouve dans l'état Runnable. Cet état signifie que le thread est créé, ainsi que son environnement et est prêt à être exécuté. Comme on va le voir dans la section suivante, ce n'est pas parce qu'un thread est prêt à être exécuté qu'il l'est réellement sur le processeur de la machine. En effet, si on repense au cas où il n'y a qu'un processeur physique sur la machine, deux threads ne pourront jamais être exécuté en même temps, même s'ils sont prêts. Le processeur sera partagé et chaque thread se verra exécuter à son tour. L'état Runnable correspond donc à cette attente, le thread est prêt et n'attend plus que le processeur pour être exécuté.

L'état Running correspond au moment où le thread est effectivement exécuté par le processeur. Vous voyez qu'un thread va pouvoir alterner successivement entre les états Runnable et Running. On verra exactement pourquoi à la section suivante. L'état RUNNABLE de l'énumération Thread.State correspond à ces deux états, on ne peut pas les distinguer avec la méthode getState de la classe Thread.

Bloqué ou en attente

Une fois qu'un thread est en cours d'exécution, certaines opérations vont le mettre en attente et il sera donc dans l'état Waiting. On a déjà vue une de ces opérations, à savoir la méthode sleep qui permet de mettre en attente un thread pour un certain temps spécifié. On verra plus loin qu'il y a également des opérations qui mettent en attente un thread pour une durée indéterminée. Un thread en attente ne consomme aucune ressource.

Une fois que soit le temps d'attente est écoulé ou qu'on demande au thread de sortir de son état d'attente, celui-ci revient à l'état Runnable. Il n'est ensuite pas garanti qu'il repasse directement à l'état Running. C'est exactement pour cela qu'on a vu à la section précédente que le temps de suspension qu'on choisit avec la méthode sleep est un temps minimum.

Un thread peut également être dans l'état Blocked lorsqu'il attend une ressource qui est actuellement détenue par une autre thread. Cette ressource peut être de type entrée/sortie (un fichier, un socket, ...), mais comme on va le voir au chapitre suivant, il peut également s'agir d'un lock. Le thread quittera cet état pour rejoindre l'état Runnable lorsqu'il aura la ressource qu'il attend.

Les états Waiting et Blocked correspondent à un seul et même état Waiting/Blocked comme vous pouvez le constater sur la figure 1. En ce qui concerne les valeurs de l'énumération Thread.State, il y a tout d'abord la valeur BLOCKED qui correspond à l'état Blocked, ensuite la valeur WAITING correspond à une attente de durée indéterminée et TIMED_WAITING à une attente de durée spécifiée (comme en cas d'appel de la méthode sleep).

Mort

Une fois qu'un thread a fini de s'exécuter, il est dit mort et passe à l'état Dead. Cela signifie simplement que le thread a terminé d'exécuter la méthode run. Une fois dans cet état, on ne peut plus rien faire avec le thread, il est notamment impossible de le démarrer à nouveau. Il ne reste plus que l'objet Thread en mémoire qu'on peut utiliser comme un objet normal. Cet état correspond à la valeur TERMINATED de l'énumération Thread.State.

Tester l'état

Certaines opérations sont interdites dans certains états. Il est par exemple impossible d'appeler la méthode start sur un thread mort. Toute tentative d'appeler une méthode dans un état où cela n'est pas autorisé se soldera par une erreur de type IllegalThreadStateException. Voyons par exemple le programme suivant :