Multithreading Java Expliqué : Concepts, Cycle de Vie et Exemples de Code Pratiques
Les applications Java ont souvent besoin d'effectuer plusieurs tâches simultanément. Ce tutoriel vous guide à travers l'exécution mono-thread vs multi-thread, le cycle de vie d'un thread, les techniques de synchronisation et des exemples de code pratiques illustrant chaque concept.
Qu'est-ce qu'un Thread Unique ?
Un thread unique en Java est la plus petite unité d'exécution. L'environnement d'exécution Java crée un thread utilisateur au démarrage de l'application, et vous pouvez ajouter des threads utilisateur ou daemon supplémentaires selon les besoins. Les threads daemon s'exécutent en arrière-plan et n'empêchent pas la JVM de s'arrêter.
Exemple d'un thread unique :
package demotest;
public class GuruThread {
public static void main(String[] args) {
System.out.println("Thread Unique");
}
}
Avantages de l'exécution mono-thread :
- Surcharge minimale – un seul contexte d'exécution est maintenu.
- Débogage et maintenance simplifiés.
Qu'est-ce que le Multithreading en Java ?
Le multithreading permet à deux ou plusieurs threads de s'exécuter concurremment, maximisant l'utilisation du CPU. Les threads partagent le même espace mémoire, donc les changements de contexte sont rapides et l'utilisation mémoire reste faible.
Exemple de création de deux threads concurrents :
package demotest;
public class GuruThread1 implements Runnable {
public static void main(String[] args) {
Thread guruThread1 = new Thread("Guru1");
Thread guruThread2 = new Thread("Guru2");
guruThread1.start();
guruThread2.start();
System.out.println("Les noms de threads sont :");
System.out.println(guruThread1.getName());
System.out.println(guruThread2.getName());
}
@Override
public void run() {
// Logique du thread ici
}
}
Avantages du multithreading :
- Interface utilisateur non-bloquante et traitement en arrière-plan.
- Résilience – une exception dans un thread n'arrête pas les autres.
Cycle de Vie d'un Thread en Java
Le cycle de vie d'un thread comprend cinq états distincts :
- Nouveau (New) – Le thread est instancié mais pas démarré.
- Exécutable (Runnable) – Le thread a été démarré et est prêt pour l'exécution.
- En cours (Running) – Le thread s'exécute activement.
- En attente (Waiting) – Le thread est suspendu jusqu'à un événement spécifique.
- Terminé (Dead) – Le thread a terminé son exécution.
Méthodes Clés des Threads
| Méthode | Description |
|---|---|
| start() | Démarre l'exécution du thread ; la JVM appelle run(). |
| sleep(long millisecondes) | Met en pause le thread courant pour la durée spécifiée. |
| getName() | Retourne le nom du thread. |
| setPriority(int nouvellePriorité) | Ajuste la priorité du thread (1-10). |
| yield() | Suggère à l'ordonnanceur de mettre en pause le thread courant. |
Exemple Pratique de Thread
Voici un exemple concis démontrant la création de thread, l'ajustement de priorité et le sommeil.
package demotest;
public class ThreadExemple1 implements Runnable {
@Override
public void run() {
// Travail du thread ici
}
public static void main(String[] args) {
Thread guruThread1 = new Thread();
guruThread1.start();
try {
Thread.sleep(1000); // pause de 1 seconde
} catch (InterruptedException e) {
e.printStackTrace();
}
guruThread1.setPriority(1);
System.out.println(guruThread1.getPriority());
System.out.println("Thread en cours d'exécution");
}
}
Exemple de sortie :
Synchronisation des Threads
Lorsque plusieurs threads accèdent à des ressources partagées, la synchronisation assure la cohérence des données. En Java, vous pouvez envelopper les sections critiques avec le mot-clé synchronized, garantissant un accès exclusif.
synchronized(objet) {
// bloc synchronisé
}
Exemple Avancé de Multithreading
Voici un exemple plus élaboré qui crée deux threads, chacun affichant son nom et un compteur avec un délai d'une seconde.
package demotest;
public class GuruThread2 {
public static void main(String[] args) {
GuruThread3 threadGuru1 = new GuruThread3("guru1");
threadGuru1.start();
GuruThread3 threadGuru2 = new GuruThread3("guru2");
threadGuru2.start();
}
}
class GuruThread3 implements Runnable {
private Thread guruthread;
private String guruname;
GuruThread3(String name) {
this.guruname = name;
}
@Override
public void run() {
System.out.println("Thread en cours d'exécution " + guruname);
for (int i = 0; i < 4; i++) {
System.out.println(i);
System.out.println(guruname);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread a été interrompu");
}
}
}
public void start() {
System.out.println("Thread démarré");
if (guruthread == null) {
guruthread = new Thread(this, guruname);
guruthread.start();
}
}
}
Sortie typique (illustrée dans l'image d'accompagnement) :
Points Clés à Retenir
- Le multithreading libère l'application des appels bloquants et permet des opérations concurrentes.
- Le cycle de vie du thread – Nouveau, Exécutable, En cours, En attente, Terminé – définit les états par lesquels passe un thread.
- La synchronisation est essentielle quand les threads partagent des données, prévenant les conditions de course.
- Les exemples de code pratiques renforcent la compréhension de la création de threads, la gestion du cycle de vie et la synchronisation.
Java
- Java Hello World : Votre premier programme
- Les Fonctions en C++ Expliquées avec des Exemples de Code Pratiques
- Maîtriser les Collections C# : Tutoriel Pratique avec Exemples Réels
- Maîtriser Java String.indexOf() : Localiser des sous-chaînes et exemples pratiques
- Comprendre Java String.charAt() : Syntaxe, type de retour, exceptions et exemple pratique
- Maîtriser la méthode Java String compareTo() : Syntaxe, cas d'usage et exemples pratiques
- Surcharge de Constructeur en Java – Expliqué avec Exemples de Code Pratiques
- Programme Java pour déterminer si un nombre est premier
- Algorithme de tri par insertion en Java : exemple clair et guide pas à pas