Programmation multitâches avec les Threads en Java - Chapitre 5 - PDF
Document Details
Uploaded by ArtisticBernoulli
Université des Sciences et de la Technologie Houari Boumediène
Tags
Summary
Ce chapitre présente la programmation multitâches avec les threads en Java. Il explique ce que sont les threads et leurs avantages, ainsi que comment les créer et exécuter en Java.
Full Transcript
# Chapitre 5 ## Programmation multitâches avec les Threads en Java. ### Contents - 5.1 Introduction - 5.2 Les Threads - 5.3 Les avantages des Threads - 5.4 La création et l'exécution d'un Thread - 5.4.1 Méthode 1 - 5.4.2 Méthode 2 - 5.5 Le cycle de vie du Thread - 5.6 La modification de l...
# Chapitre 5 ## Programmation multitâches avec les Threads en Java. ### Contents - 5.1 Introduction - 5.2 Les Threads - 5.3 Les avantages des Threads - 5.4 La création et l'exécution d'un Thread - 5.4.1 Méthode 1 - 5.4.2 Méthode 2 - 5.5 Le cycle de vie du Thread - 5.6 La modification de la priorité d'un Thread - 5.7 Conclusion ## 5.1 Introduction Le multitâche est le fait d'exécuter plusieurs tâches (ou processus) simultanément et sans conflit. Par exemple écouter de la musique et lire son courrier en même temps. Un système mono-processeur simule le multitâche en attribuant un temps (un quantum ou temps déterminé à l'avance) de traitement à chaque processus. Un programme est dit multitâche s'il est capable de lancer plusieurs parties de son code en même temps. A chaque partie du code sera associé un sous processus pour permettre l'exécution en parallèle. On peut appliquer la multiprogrammation au sein d'un même programme. On dit dans ce cas que le programme est formé de plusieurs parties indépendantes qui peuvent communiquer entre eux et partager des données. Le contrôle d'exécution de ces parties se fait au niveau de ce programme [6] [7]. ## 5.2 Les Threads Un Thread est une unité d'exécution faisant partie d'un programme. Cette unité fonctionne de façon autonome et parallèlement à d'autres Threads. En fait, sur une machine mono-processeur, chaque unité se voit attribuer des intervalles de temps au cours desquels elles ont le droit d'utiliser le processeur pour accomplir leurs traitements. Il est important de préciser qu'un Thread n'est pas un processus. En effet, les processus vivent dans des espaces virtuels isolés alors que les Threads sont des traitements qui vivent ensemble au sein d'un même processus. Les Threads partagent la même mémoire contrairement aux processus. Un Thread est donc une portion de code capable de s'exécuter en parallèle à d'autres traitements. Ils sont utiles dans plusieurs cas et parfois même nécessaires [6] [7]. ## 5.3 Les avantages des Threads Le principal avantage des Threads est de pouvoir répartir différents traitements d'un même programme en plusieurs unités distinctes pour permettre leur exécution simultanée. Ils servent à plusieurs choses comme par exemple [6] [7]: - Faire des traitements en tâche de fond, c'est le cas de la coloration syntaxique des éditeurs (Eclipse ou NetBeans par exemple). - Exécuter plusieurs instances d'un même code pour accélérer le traitement. - S'adresser de manière personnelle à plusieurs clients simultanément comme les serveurs HTTP ou les Chat. Les Threads ne s'exécutent pas en même temps mais en temps partagé, c'est pour cette raison qu'il est important pour un Thread de toujours laisser une chance aux autres de s'exécuter. La gestion de ces unités de temps par le système d'exploitation est appelée Scheduling. Il existe deux grands types de Schedule [6] [7]: - Le découpage de temps qui consiste à attribuer un intervalle de temps prédéfini quelque soit le Thread et la priorité qu'il peut avoir. - La préemption utilisé dans quelques systèmes (comme Unix) qui consiste à attribuer des intervalles de temps en tenant compte de la priorité d'exécution de chaque Thread. Les Threads possédant une priorité plus élevée s'exécutent avant ceux possédant une priorité plus faible. ## 5.4 La création et l'exécution d'un Thread La classe Thread possède plusieurs constructeurs: un constructeur par défaut et plusieurs autres qui peuvent avoir un ou plusieurs des paramètres suivants (Tableau 5.1): | Paramètre | Rôle | |---|---| | Un nom | Le nom du Thread. | | Un objet qui implémente l'interface Runnable | L'objet qui contient les traitements du Thread. | | Un groupe | Le groupe auquel sera rattaché le Thread. | Un Thread possède un nom. Si aucun nom particulier n'est donné dans le constructeur du Thread, un nom par défaut composé du suffixe Thread- suivi d'un numéro séquentiel incrémenté automatiquement lui est attribué. Il existe deux façons pour créer un Thread en Java: 1. La classe hérite de la classe Thread: Vous pouvez créer une nouvelle classe qui dérive de la classe Thread. Ensuite, il faut redéfinir la méthode run() qui représente la méthode que le Thread va exécuter. 2. La classe implémente l'interface Runnable: Vous pouvez implémenter l'interface Runnable et définir la méthode run(). Ensuite il suffit de créer un objet Thread en lui passant la classe en paramètre. Pour lancer l'exécution d'un Thread, il faut exécuter la méthode start() et en aucun cas exécuter vous-même la méthode run(). ### 5.4.1 Méthode 1 Il faut créer une classe qui hérite de la classe Thread. Il suffit de redéfinir la méthode run() pour y inclure les traitements à exécuter par le Thread. ```java class MyThread extends Thread { public void run() { for (int count = 0; count < 4; count++) { System.out.println( count + "From: " + getName()); } } } ``` Pour créer et exécuter un tel Thread, il faut instancier un objet et appeler sa méthode start(). ```java class TestThread { public static void main(String[] args) { MyThread first = new MyThread(); MyThread second = new MyThread(); first.start(); second.start(); } } ``` ### 5.4.2 Méthode 2 L'interface Runnable doit être implémentée par toute classe qui contiendra des traitements à exécuter dans un Thread. Cette interface ne définit qu'une seule méthode: void run(). Dans les classes qui implémentent cette interface, la méthode run() doit être redéfinie pour contenir le code des traitements qui seront exécutés dans le Thread. Si on utilise l'interface Runnable, il faut uniquement redéfinir sa seule et unique méthode run() pour y inclure les traitements à exécuter dans le Thread. ```java public class MyThreadR implements Runnable { public void run() { int i = 0; for (i = 0; i < 10; i++) { System.out.println("Test" + i); } } } ``` Pour pouvoir utiliser cette classe dans un Thread, il faut l'associer à un objet de la classe Thread. Ceci se fait en utilisant un des constructeurs de la classe Thread qui accepte un objet implémentant l'interface Runnable en paramètre. ```java public class TestThreadR { public static void main(String[] args) { Thread t = new Thread (new MyThreadR()); t.start(); } } ``` ## 5.5 Le cycle de vie du Thread La classe Thread possède plusieurs méthodes pour gérer le cycle de vie du Thread. Parmi ces méthodes (Tableau 5.2): | Méthode | Rôle | |---|---| | void destroy() | met fin brutalement au Thread. | | int getPriority() | renvoie la priorité du Thread. | | boolean isInterrupted() | renvoie un booléen qui indique si le Thread est actif ou non. | | boolean isAlive() | renvoie un booléen qui indique si le Thread a été interrompu. | | void resume() | reprend l'exécution du Thread() suspendu par suspend(). | | void run() | méthode qui contient le code qui sera exécuté par le Thread. | | void sleep(long) | mettre le Thread en attente durant le temps exprimé en millisecondes fourni en paramètre. | | void start() | démarrer le Thread et exécuter la méthode run(). | | void stop() | arrêter le Thread. | | void suspend() | suspend le Thread jusqu'au moment où il sera relancé par la méthode resume(). | La Figure 5.1 représente le cycle de vie d'un Thread. **Remarque:** A partir du JDK 1.2, les méthodes stop(), suspend() et resume() sont dépréciées. Le plus simple et le plus efficace est de définir un attribut booléen dans la classe du Thread initialisé à true. Il faut définir une méthode qui permet de basculer cet attribut à false. Enfin dans la méthode run() du Thread, il suffit de continuer les traitements tant que l'attribut est à true et que les autres conditions fonctionnelles d'arrêt du Thread sont négatives [6] [7]. ### Exemple Exécution du Thread jusqu'à l'appui sur la touche Entrée. ```java public class MonThread6 extends Thread { private boolean actif = true; public static void main(String[] args) { try { MonThread6 t = new MonThread6(); t.start(); System.in.read();t.arreter(); } catch (Exception e) { e.printStackTrace();} } public void run() { int i = 0; while (actif) { System.out.println("i=" + i); i++;}} public void arreter () { actif = false;} } ``` ## 5.6 La modification de la priorité d'un Thread La priorité d'un Thread varie de 1 à 10, la valeur 5 étant la valeur par défaut. L'attribution d'une priorité supérieure à un Thread permet d'augmenter ses chances d'exécution. La classe Thread définit trois priorités: - MIN_PRIORITY: priorité inférieure. - NORM_PRIORITY: priorité standard. - MAX_PRIORITY: priorité supérieure. Pour déterminer ou modifier la priorité d'un Thread, la classe Thread contient les méthodes suivantes: - int getPriority(): retourne la priorité d'un Thread. - void setPriority(int): modifie la priorité d'un Thread. ### Exemple ```java class TestThread { public static void main(String[] args) { MyThread first = new MyThread(); MyThread second = new MyThread(); first.setPriority (1); second.setPriority (2); first.start(); second.start(); System.out.println("Thread. MIN PRIORITY__=" + first.MIN PRIORITY); System.out.println("Thread.NORM_PRIORITY_=" + first.NORM PRIORITY); System.out.println("Thread.MAX PRIORITY=" + first.MAX PRIORITY); System.out.println("Thread.MAX PRIORITY=" + first.getPriority()); } } ``` ## 5.7 Conclusion Dans ce chapitre, nous avons présenté le concept de la programmation multitâches avec l'utilisation des threads. Il s'agit de: - Apprendre à créer, travailler avec et arrêter des threads. - Apprendre comment exécuter plusieurs tâches simultanément (en parallèle) par l'utilisation des threads en langage Java. - Savoir reconnaître les données partagées entre différents threads. - Être capable d'orchestrer la synchronisation de threads.