Thread ou implémenter l'interface Runnable. Cette section vous montre comment créer, démarrer et gérer des threads dans vos programmes Java.
12.2Création de threads
12.2.1 – Méthode 1 : Étendre la classe Thread
La première méthode consiste à créer une classe qui étend la classe Thread et à redéfinir la méthode run().
📝 Structure de base
public class MonThread extends Thread {
@Override
public void run() {
// Code à exécuter dans le thread
System.out.println("Thread en cours d'exécution");
}
}
🚀 Utilisation
public class ExempleThread {
public static void main(String[] args) {
// Créer une instance du thread
MonThread thread = new MonThread();
// Démarrer le thread (appelle automatiquement run())
thread.start();
// Le code continue ici pendant que le thread s'exécute
System.out.println("Code du thread principal");
}
}
run() directement ! Utilisez toujours start() pour démarrer un thread. Appeler run() directement exécute le code dans le thread actuel, pas dans un nouveau thread.
đź’» Exemple complet : Thread avec boucle
public class ThreadCompteur extends Thread {
private String nom;
private int max;
public ThreadCompteur(String nom, int max) {
this.nom = nom;
this.max = max;
}
@Override
public void run() {
for (int i = 1; i <= max; i++) {
System.out.println(nom + " : " + i);
try {
Thread.sleep(500); // Pause de 500ms
} catch (InterruptedException e) {
System.out.println(nom + " interrompu");
return;
}
}
System.out.println(nom + " terminé");
}
}
// Utilisation
public class TestThreads {
public static void main(String[] args) {
ThreadCompteur t1 = new ThreadCompteur("Thread-1", 5);
ThreadCompteur t2 = new ThreadCompteur("Thread-2", 5);
t1.start(); // Démarrer le premier thread
t2.start(); // Démarrer le deuxième thread
// Les deux threads s'exécutent en parallèle
}
}
- Les messages des deux threads seront mélangés car ils s'exécutent simultanément
- L'ordre d'affichage peut varier à chaque exécution
- Les deux threads s'exécutent en parallèle, pas séquentiellement
❌ Limitation de cette approche
Étendre Thread a une limitation : Java ne supporte pas l'héritage multiple. Si votre classe doit déjà étendre une autre classe, vous ne pouvez pas étendre Thread.
12.2.2 – Méthode 2 : Implémenter l'interface Runnable (recommandé)
La méthode recommandée est d'implémenter l'interface Runnable. Cette approche est plus flexible car elle permet à votre classe d'étendre une autre classe si nécessaire.
📝 Structure de base
public class MaTache implements Runnable {
@Override
public void run() {
// Code à exécuter dans le thread
System.out.println("Tâche en cours d'exécution");
}
}
🚀 Utilisation
public class ExempleRunnable {
public static void main(String[] args) {
// Créer une instance de la tâche
MaTache tache = new MaTache();
// Créer un thread avec la tâche
Thread thread = new Thread(tache);
// Démarrer le thread
thread.start();
}
}
💻 Exemple complet : Runnable avec paramètres
public class TacheCompteur implements Runnable {
private String nom;
private int max;
public TacheCompteur(String nom, int max) {
this.nom = nom;
this.max = max;
}
@Override
public void run() {
for (int i = 1; i <= max; i++) {
System.out.println(nom + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println(nom + " interrompu");
return;
}
}
System.out.println(nom + " terminé");
}
}
// Utilisation
public class TestRunnable {
public static void main(String[] args) {
TacheCompteur tache1 = new TacheCompteur("Tâche-1", 5);
TacheCompteur tache2 = new TacheCompteur("Tâche-2", 5);
Thread t1 = new Thread(tache1);
Thread t2 = new Thread(tache2);
t1.start();
t2.start();
}
}
🎯 Avantages de Runnable
- Flexibilité : Votre classe peut étendre une autre classe
- Réutilisabilité : Une même tâche peut être exécutée par plusieurs threads
- Séparation des responsabilités : La tâche (Runnable) est séparée du thread (Thread)
- Recommandé : C'est la méthode recommandée par Oracle
12.2.3 – Méthode 3 : Expressions lambda (Java 8+)
Depuis Java 8, vous pouvez utiliser des expressions lambda pour créer des threads de manière concise, car Runnable est une interface fonctionnelle.
📝 Syntaxe avec lambda
// Thread simple avec lambda
Thread thread = new Thread(() -> {
System.out.println("Thread avec lambda");
});
thread.start();
💻 Exemples variés
Exemple 1 : Thread simple
new Thread(() -> System.out.println("Hello")).start();
Exemple 2 : Thread avec boucle
new Thread(() -> {
for (int i = 1; i <= 5; i++) {
System.out.println("Compteur : " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Exemple 3 : Plusieurs threads
for (int i = 1; i <= 3; i++) {
final int numero = i; // Doit ĂŞtre final ou effectively final
new Thread(() -> {
System.out.println("Thread " + numero + " en cours");
}).start();
}
final ou "effectively final" (qui ne sont jamais modifiées après leur initialisation).
12.2.4 – Méthodes utiles de la classe Thread
La classe Thread fournit plusieurs méthodes utiles pour contrôler et obtenir des informations sur les threads.
🔧 Méthodes de contrôle
start()
Démarre le thread (appelle run() dans un nouveau thread).
thread.start(); // Démarre le thread
sleep(long millis)
Met le thread en pause pour un nombre de millisecondes.
try {
Thread.sleep(1000); // Pause de 1 seconde
} catch (InterruptedException e) {
e.printStackTrace();
}
join()
Attend que le thread se termine avant de continuer.
Thread thread = new Thread(() -> {
// Code du thread
});
thread.start();
thread.join(); // Attendre que le thread se termine
System.out.println("Thread terminé");
interrupt()
Interrompt le thread (envoie un signal d'interruption).
thread.interrupt(); // Interrompre le thread
📊 Méthodes d'information
getName() et setName()
Thread thread = new Thread(() -> {});
thread.setName("MonThread");
System.out.println(thread.getName()); // Affiche : MonThread
getId()
long id = thread.getId(); // ID unique du thread
getState()
Thread.State etat = thread.getState();
System.out.println(etat); // NEW, RUNNABLE, BLOCKED, etc.
isAlive()
boolean vivant = thread.isAlive(); // true si le thread est actif
currentThread()
Thread actuel = Thread.currentThread(); // Thread actuellement exécuté
💡 Points clés à retenir
- Étendre Thread : Simple mais limite l'héritage
- Implémenter Runnable : Recommandé, plus flexible
- Lambda : Syntaxe concise pour les tâches simples
- start() : Démarre le thread (ne pas appeler run() directement)
- sleep() : Met en pause le thread
- join() : Attend la fin du thread
- interrupt() : Interrompt le thread
Runnable (ou lambda) plutôt que d'étendre Thread. C'est plus flexible et c'est la pratique recommandée. Réservez l'extension de Thread uniquement si vous avez besoin de modifier le comportement de la classe Thread elle-même.