Threads en Java — Résumé 80/20 EST Casablanca — Prof.
HASSOUNI Larbi
Résumé 80/20 — Tout ce que vous devez sa
ads en Java
01 Concepts de base 06 wait() / notify()
02 Créer un Thread 07 Threads Démons
03 Cycle de vie (5 états) 08 Pool de Threads (Executors)
04 Méthodes essentielles 09 Priorités
05 Synchronisation 10 Pièges d'examen
■ 01 — Concepts de base
Thread = fil d'exécution léger qui partage la mémoire avec les autres threads du même processus.
Critère Processus Thread
Mémoire Espace propre (isolé) Partagée avec les autres threads
Ressources Lourdes Légères
Communication Inter-processus (IPC) Variables partagées directement
Création Lente Rapide
✓ Utilité : GUI réactive, serveur traitant plusieurs clients, calcul parallèle sur multi-coeurs.
■ 02 — Créer un Thread (2 méthodes)
Méthode 1 : extends Thread Méthode 2 : implements Runnable ■
• Simple à écrire • Peut hériter d'une autre classe
• Redéfinir run() • Partage de données plus facile
• Instancier et appeler start() • MÉTHODE RECOMMANDÉE
Méthode 1 — extends Thread
class MonThread extends Thread {
public void run() {
// Code exécuté par le thread
[Link]("Bonjour depuis le thread !");
}
}
// Utilisation
MonThread t = new MonThread();
[Link](); // ← TOUJOURS start(), jamais run() directement !
Méthode 1 : extends Thread
Méthode 2 — implements Runnable (recommandée)
Page 1
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
class MaTache implements Runnable {
public void run() {
[Link]("Tâche en cours...");
}
}
// Utilisation
MaTache tache = new MaTache();
Thread t = new Thread(tache); // on passe le Runnable au Thread
[Link]();
Méthode 2 : implements Runnable
■ PIÈGE : Appeler run() directement n'est PAS du multithreading ! Le code s'exécute dans le thread appelant.
■ PIÈGE : On ne peut pas relancer un thread déjà démarré → IllegalThreadStateException
Page 2
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
■ 03 — Cycle de vie d'un Thread (5 états)
État Description Déclencheur
NEW Thread créé, pas encore démarré new Thread()
RUNNABLE Prêt à s'exécuter, attend le CPU start()
BLOCKED Attend l'acquisition d'un moniteur Attente synchronized
WAITING /
En attente d'une notification ou d'un délai wait(), sleep(), join()
TIMED_WAITING
DEAD Thread terminé, ne peut plus être relancé Fin de run() ou exception
NEW → start() → RUNNABLE → scheduler → RUNNING → fin run() → DEAD
↕ sleep()/wait()/join() → WAITING/TIMED_WAITING | notify()/fin délai → retour RUNNABLE
■ 04 — Méthodes essentielles
Méthode Rôle Note importante
start() Lance le thread (NEW → RUNNABLE) ■ Ne jamais appeler run() directement !
run() Code exécuté par le thread Définir dans Thread ou Runnable
sleep(ms) Pause en millisecondes ■ Ne libère PAS le moniteur
join() Attend la fin d'un autre thread [Link]() bloque jusqu'à mort de th
yield() Cède la main (priorité ≥) Aucune garantie
interrupt() Lève le flag d'interruption Lance InterruptedException si endormi
isInterrupted() Teste le flag (ne le réinitialise pas) Méthode d'instance
interrupted() Teste ET réinitialise le flag Méthode statique
setDaemon(true) Marque le thread comme démon ■ AVANT start() !
getPriority() Retourne la priorité (1-10) Défaut : NORM_PRIORITY = 5
isAlive() Thread encore en vie ? false si DEAD
Exemple — join() : attendre la fin d'un thread
Thread t1 = new Thread(new Runnable() {
public void run() {
[Link]("t1 travaille...");
}
});
[Link]();
[Link](); // le thread appelant attend que t1 soit mort
[Link]("t1 est terminé, je continue !");
join() : synchroniser la fin d'exécution
Exemple — sleep() : mettre en pause
Page 3
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
try {
[Link]("Début de pause...");
[Link](2000); // pause de 2 secondes
[Link]("Pause terminée !");
} catch (InterruptedException e) {
// gérer l'interruption pendant le sommeil
}
sleep() : pause sans libérer le moniteur
Page 4
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
■ 05 — Synchronisation
Le problème
Si 2 threads accèdent simultanément à une variable partagée sans synchronisation, le résultat est imprévisible.
// PROBLÈME : x = 2, deux threads font x = x + 1
// Thread T1 lit x (2) → T2 lit x (2)
// T1 calcule 3 → T2 calcule 3
// T1 écrit 3 → T2 écrit 3
// Résultat : x = 3 au lieu de 4 !
Race condition : résultat imprévisible sans synchronisation
La solution : mot-clé synchronized
Chaque objet Java possède un moniteur (verrou). Le mot-clé synchronized garantit qu'un seul thread à la fois
exécute la méthode.
class Compte {
private double solde;
// synchronized = verrou automatique sur 'this'
public synchronized void deposer(double somme) {
solde = solde + somme; // maintenant atomique !
}
public synchronized double getSolde() {
return solde;
}
}
// Trois threads peuvent déposer en parallèle sans problème :
Thread t1 = new Thread(() -> { for(int i=0;i<100;i++) [Link](1000); });
Thread t2 = new Thread(() -> { for(int i=0;i<100;i++) [Link](1000); });
[Link](); [Link]();
// Résultat garanti : 200 000
synchronized : garantit l'accès exclusif
Règle du moniteur Explication
Un seul à la fois Un seul thread peut posséder le moniteur d'un objet
File d'attente Les autres threads sont mis en état BLOCKED
Libération auto Le moniteur est libéré en quittant le bloc synchronized
Méthode static sync Bloque le moniteur de la CLASSE entière, pas d'une instance
Réentrant Un thread peut appeler d'autres méthodes sync du même objet
■ La synchronisation nuit aux performances. N'utiliser QUE là où c'est nécessaire.
■ 06 — wait() / notify() / notifyAll()
Utilisés pour la communication entre threads. Exemple classique : Producteur / Consommateur.
Page 5
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
class Depot {
private int nbJetons = 0;
// Consommateur : attend qu'il y ait des jetons
public synchronized void prendreJeton() throws InterruptedException {
while (nbJetons == 0) {
wait(); // libère le moniteur ET bloque le thread
}
nbJetons--;
[Link]("Jeton pris. Restant : " + nbJetons);
}
// Producteur : ajoute des jetons et réveille les consommateurs
public synchronized void ajouterJetons(int n) {
nbJetons += n;
[Link]("Jetons ajoutés : " + n);
notifyAll(); // réveille TOUS les threads en attente
}
}
Producteur/Consommateur avec wait() et notifyAll()
Méthode Rôle Important
wait() Bloque le thread ET libère le moniteur ■ Dans synchronized uniquement
notify() Réveille UN thread (indéterminé) Risqué : on ne sait pas lequel
notifyAll() Réveille TOUS les threads en attente ✓ Préférable à notify()
■ Un notify/notifyAll émis alors qu'aucun thread n'attend est PERDU — il n'affecte pas les wait() futurs.
■ Différence clé : sleep() ne libère PAS le moniteur, wait() LE LIBÈRE.
Page 6
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
■ 07 — Threads Démons (Daemon Threads)
Thread utilisateur Thread Démon
• Type par défaut • Marqué avec setDaemon(true)
• La JVM reste en vie tant qu'il en existe • La JVM s'arrête si il ne reste que des démons
• Tâches principales du programme • Tâches d'arrière-plan (ex: GC, finalizer)
Thread t = new Thread(new MaTache());
[Link](true); // ← OBLIGATOIRE avant start() !
[Link]();
// Quand tous les threads utilisateurs meurent,
// la JVM tue automatiquement les threads démons.
Création d'un thread démon
■ setDaemon(true) DOIT être appelé AVANT start(). Sinon → IllegalThreadStateException
■ 08 — Pool de Threads (Executors)
Créer et détruire des threads à la volée est coûteux. Un pool de threads réutilise des threads existants pour plusieurs
tâches.
import [Link].*;
// Créer un pool de 3 threads maximum
ExecutorService executor = [Link](3);
// Soumettre des tâches (elles s'exécutent en parallèle)
[Link](new Runnable() {
public void run() { [Link]("Tâche 1"); }
});
[Link](new Runnable() {
public void run() { [Link]("Tâche 2"); }
});
[Link](new Runnable() {
public void run() { [Link]("Tâche 3"); }
});
[Link](); // ← NE PAS OUBLIER ! Libère les ressources
Pool de 3 threads avec [Link]
✓ Avantage : pas de création/destruction répétée de threads → meilleures performances pour de nombreuses tâches.
■ 09 — Priorités des Threads
Constante Valeur Usage
MIN_PRIORITY 1 Tâches d'arrière-plan peu urgentes
NORM_PRIORITY 5 Valeur par défaut pour tous les threads
MAX_PRIORITY 10 Tâches très urgentes
Page 7
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
Thread t = new Thread(new MaTache());
[Link](Thread.MAX_PRIORITY); // priorité = 10
[Link]();
// Un thread hérite de la priorité de son créateur.
// Modifier avec setPriority(int n) entre 1 et 10.
Modifier la priorité d'un thread
■ Un thread de haute priorité prend la main AVANT un thread de basse priorité, mais ce n'est pas garanti.
Page 8
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
■ 10 — Pièges d'Examen & Points Clés
■ start() ≠ run()
Appeler run() directement exécute le code dans le thread appelant, sans créer de nouveau thread.
MonThread t = new MonThread();
[Link](); // ← FAUX : pas de nouveau thread créé !
[Link](); // ← CORRECT : crée et lance le thread
■ sleep() ne libère PAS le moniteur
Contrairement à wait(), sleep() garde le verrou pendant la pause.
synchronized(obj) {
[Link](1000); // garde le moniteur pendant 1s
[Link](); // libère le moniteur pendant l'attente
}
■ setDaemon() avant start()
Appeler setDaemon() après start() lève une IllegalThreadStateException.
Thread t = new Thread(task);
[Link](true); // ← doit être AVANT start()
[Link]();
■ wait/notify dans synchronized
Ces méthodes nécessitent de posséder le moniteur de l'objet.
// CORRECT :
synchronized(obj) { [Link](); }
// FAUX : IllegalMonitorStateException
[Link](); // sans synchronized
■ Ne pas relancer un thread
Un thread déjà démarré (même terminé) ne peut pas être relancé.
Thread t = new Thread(task);
[Link]();
[Link](); // ← IllegalThreadStateException !
■ while vs if avec wait()
Toujours utiliser while (pas if) pour tester la condition après wait().
Page 9
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
// CORRECT (résiste aux réveils spurieux) :
while (condition == false) { wait(); }
// FAUX (peut planter si réveil inattendu) :
if (condition == false) { wait(); }
Page 10
Threads en Java — Résumé 80/20 EST Casablanca — Prof. HASSOUNI Larbi
■ Tableau de Récapitulation Ultra-Rapide
Concept À retenir Code-clé
Créer thread extends Thread OU implements Runnable [Link]()
Lancer start() crée un nouveau thread [Link]() ← PAS run()
Pause sleep() garde le moniteur [Link](ms)
Attendre fin join() bloque jusqu'à mort [Link]()
Protéger accès synchronized + moniteur public synchronized void m()
Coopération wait libère, notifyAll réveille [Link]() / [Link]()
Démon setDaemon AVANT start [Link](true); [Link]()
Pool [Link] [Link](task); [Link]()
Priorité MIN=1, NORM=5, MAX=10 [Link](10)
■ Règle des 80/20 : maîtrisez ces 10 concepts et vous avez 80% des points couverts. Concentrez-vous sur
synchronized, wait/notify et le cycle de vie — ce sont les sujets les plus fréquents aux examens.
Page 11