Les threads : introduction java.lang.Thread java.lang.Runnable Cours Java - F. Michel Processes and Threads ● ● ● ● ● Dans la programmation concurrente, il existe principalement deux unités d'exécution : les processus et les threads. L'exécution des processus et des threads est gérée par l'OS (slicing). Un processus possède son propre environnement d'exécution (ressources systèmes) En général on a un processus par application (mais on peut faire coopérer des processus (IPC : Inter Process Communication) La plupart des JVM tourne sur un seul processus Processes and Threads ● ● ● ● Un thread est souvent appelé un « processus léger » (lightweight process) Les threads existe dans un processus (au moins un thread par processus) Les threads nécessitent moins de ressources : ils partagent les ressources du processus père : mémoire, fichiers ouverts, etc. L'exécution d'une jvm est « multi-threadée »: les threads constituent un aspect essentiel du langage Java Exécution « point de vue » utilisateur ● ● ● En général, le code s'exécute sur un seul fil d'exécution: le « main thread » instruction instruction instruction L'ordre dans lequel les instructions sont exécutées est garanti. Il n'est pas possible de faire des choses « en parallèle » instruction instruction instruction t Exécution multi-threadée ● Chaque thread possède son code à exécuter instruction Thread1 instruction Thread2 ● L'ordre global dans lequel les instructions sont exécutées n'est pas garanti. instruction Thread1 instruction Thread1 instruction Thread2 instruction Thread1 ● Il est possible de faire des choses « en parallèle » t Le « main » thread Autres threads de la jvm java.lang.Thread java.lang.Thread java.lang.Thread.State java.lang.Thread ● ● ● Première manière de créer un nouveau thread : étendre la classe Thread Le code à exécuter doit être implémenté dans la méthode public void run() (héritée : surcharge) La méthode start() héritée de la classe démarre le thread Créer un nouveau thread (1) java.lang.Runnable ● ● ● Deuxième manière de créer un nouveau thread : créer un objet qui implémente l'interface Runnable Le code à exécuter doit être implémenté dans la méthode public void run() (obligatoire) On passe l'objet en paramètre du constructeur d'un thread Créer un nouveau thread (2) La méthode static sleep La méthode static sleep Comment stopper un thread ? ● Automatiquement : – ● Manuellement : – ● Un thread se termine de lui même lorsqu'il n'y a plus rien à exécuter dans la méthode run depuis le thread courant (ou depuis un autre thread) en utilisant la méthode interrupt() sur l'instance visée (cf. Javadoc) Mais cela ne suffit pas... Comment stopper un thread ? ● ● Que faire pour savoir si le thread a été interrompu si les méthodes utilisées ne renvoient pas d'exception du type InterruptedException ? Il faut régulièrement tester si le thread n'a pas été interrompu. Synchronisation de threads ● La méthode join() appliquée sur un objet t de type Thread permet d'attendre la fin de l'exécution de t : ● t.join(); // attendre la fin de t Manipulation de données partagées Manipulation de données partagées Soient 2 threads A et B, avec c=0 dans la classe Counter, si A invoque increment au « même moment » que B invoque decrement, on peut avoir la séquence d'actions suivante : 1. Thread A: accède c → valeur 0. 2. Thread B: accède c → valeur 0. 3. Thread A: Incrémente la valeur accédée → 1. 4. Thread B: Décrémente la valeur accédée → -1. 5. Thread A: Enregistre le résultat dans c → c = 1. 6. Thread B: Enregistre le résultat dans c → c = - 1. Le calcul de A est perdu !! Méthodes synchronisées ● Avec le mot clé synchronized : Méthodes synchronisées ● Lorsqu'une méthode synchronisée est invoquée par un thread : – Aucune autre méthode synchronisée de l'objet ne peut être invoquée avant la fin de l'exécution de ce thread : l'objet est « locked ». – Tous les changements effectués seront visibles par les autres threads (relation de précédence) Synchronisation d'instructions Objet locké Synchronisation d'instructions Accès atomiques ● Certaines instructions sont atomiques, i.e. sont exécutées entièrement par un thread en une seule fois. – Attention : i++ n'est pas une instruction atomique (lecture + écriture) – La lecture et l'écriture des références et des types primitifs sont atomiques (sauf long et double) – La lecture et l'écriture des variables déclarées comme volatile (mot clé java, e.g. private) sont atomiques (attention : toujours pas i++) Programmation concurrente depuis 1.5 ● Java 1.5 a introduit de nouveaux packages : – Java.util.concurrent (gestion de threads et de structures de données adaptées) – Java.util.concurrent.atomic (variables thread safe) – Java.util.concurrent.locks (conditions personnalisées) Package java.util.concurrent Package java.util.concurrent.atomic java.util.concurrent.locks