Multithreading en Java
Java est un langage de programmation multithread, ce qui signifie que nous pouvons développer un programme multithread en utilisant Java. Un programme multithread contient deux composants ou plus pouvant être exécutés simultanément. Chaque composant peut gérer une tâche différente en même temps, en exploitant au mieux les ressources disponibles, notamment lorsque votre ordinateur dispose de plusieurs processeurs.
Par définition, le multitâche se produit lorsque plusieurs processus partagent des ressources communes telles qu’un processeur. Le multi-threading hérite l’idée du multitâche aux applications dans lesquelles vous pouvez subdiviser des opérations spécifiques au sein d’une application unique en threads individuels. Chacun des threads peut être exécuté en parallèle. Le système d’exploitation divise le temps de traitement non seulement entre différentes applications, mais également entre chaque thread au sein d’une application.
Le multi-threading vous permet d’écrire de manière à ce que plusieurs activités puissent se dérouler simultanément dans le même programme.
Un thread peut être dans l’un des états suivants:
- NEW : Un thread qui n’a pas encore démarré est dans cet état.
- RUNNABLE : Un thread qui s’exécute sur la machine virtuelle Java est dans cet état.
- BLOCKED : Un thread bloqué en attente d’un verrouillage du moniteur se trouve dans cet état.
- WAITING : Un thread qui attend indéfiniment qu’un autre thread effectue une action particulière se trouve dans cet état.
- TIMED_WAITING : Un thread qui attend qu’un autre thread exécute une action pendant une durée d’attente maximale se trouve dans cet état.
- TERMINATED : Un thread passe à l’état terminé lorsqu’il termine sa tâche.
Un thread ne peut être que dans un seul état à un moment donné.
Comment créer un thread en Java?
Il existe deux manières pour créer un thread en Java:
- En héritant la classe Thread.
- En implémentant l’interface Runnable.
- getName(): Il est utilisé pour obtenir le nom d’un thread.
- getPriority(): Obtenir la priorité d’un thread
- isAlive(): Détermine si un thread est toujours en cours d’exécution
- join(): Attend la fin d’un thread
- run(): point d’entrée pour le thread
- sleep(): suspendre un thread pour une période donnée
- start(): démarre un thread en appelant sa méthode run()
Méthode 1: Création de thread en héritant la classe Thread
class MultithreadingEx extends Thread{ public void run(){ System.out.println("Mon thread est en cours d'exécution."); } public static void main(String args[]){ MultithreadingEx thread = new MultithreadingEx(); thread.start(); } }
Sortie:
Mon thread est en cours d'exécution.
Méthode 2: Création de threads en implémentant l’interface Runnable
class MultithreadingEx implements Runnable{ public void run(){ System.out.println("My thread is in running state."); } public static void main(String args[]){ MultithreadingEx thread =new MultithreadingEx(); Thread thread = new Thread(thread); thread.start(); } }
Sortie:
Mon thread est en cours d'exécution.
Synchronisation
Le multithreading introduit un comportement asynchrone aux programmes Java. Si un thread est en train d’écrire des données, un autre thread peut lire les mêmes données à ce moment-là. Cela peut amener une incohérence.
Lorsque deux ou plusieurs threads ont besoin d’accéder à une ressource partagée, la ressource ne doit être utilisée que par une seule ressource à la fois, pour cela on utilise la synchronisation.
Pour implémenter le comportement synchrone, Java a une méthode synchrone. Une fois qu’un thread est dans une méthode synchronisée, aucun autre thread ne peut appeler une autre méthode synchronisée sur le même objet. Tous les autres threads attendent alors que le premier thread sorte du bloc synchronisé.
Synchronized(object) { // code à synchroniser }
Classe Thread vs Interface Runnable
- Si nous héritant la classe Thread, notre classe ne pourra hériter aucune d’autre classe, car Java ne support pas l’héritage multiple. D’ailleurs, si nous implémentons l’interface Runnable, notre classe peut toujours étendre d’autres classes de base.
- Nous pouvons obtenir les fonctionnalités de base d’un thread en héritant la classe Thread, car elle fournit des méthodes intégrées telles que yield(), interrupt(), etc. qui ne sont pas disponibles dans l’interface Runnable.