Classe Thread Java

La classe Thread est une classe fondamentale en Java pour créer et gérer des threads.

En Java, chaque thread est une instance de la classe Thread. Un thread peut être compris comme une "sous-tâche" s'exécutant indépendamment dans un programme, ce qui permet au programme d'effectuer plusieurs opérations simultanément.

Il existe deux façons de créer des threads en Java :

  1. Étendre la classe Thread
  2. Implémenter l'interface Runnable

Utilisation de base de la classe Thread

Création de threads

Exemple

// Méthode 1 : étendre la classe Thread
class MyThread extends Thread {
    public void run() {
        System.out.println("Thread is running");
    }
}

// Méthode 2 : implémenter l'interface Runnable
class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Thread is running");
    }
}

public class Main {
    public static void main(String[] args) {
        // Utilisation de l'approche par héritage
        MyThread thread1 = new MyThread();
        thread1.start();
       
        // Utilisation de l'approche par interface
        Thread thread2 = new Thread(new MyRunnable());
        thread2.start();
    }
}

Cycle de vie des threads

Les threads Java ont les états suivants :

  • NEW: thread nouvellement créé, la méthode start() n'a pas encore été appelée
  • RUNNABLE: état exécutable, peut être en cours d'exécution ou en attente de temps CPU
  • BLOCKED: le thread est bloqué, en attente d'acquisition du verrou du moniteur
  • WAITING: État d'attente, en attente que d'autres threads effectuent des opérations spécifiques
  • TIMED_WAITING: État d'attente temporisé
  • TERMINATED: Le thread s'est terminé

Méthodes courantes de la classe Thread

Méthodes de contrôle de base

Exemple

Thread thread = new Thread(() -> {
    System.out.println("Thread executing");
});

thread.start();  // Démarrer le thread
thread.join();   // Attendre que le thread se termine
thread.sleep(1000); // Le thread dort pendant 1 seconde

Priorité des threads

Exemple

thread.setPriority(Thread.MAX_PRIORITY);  // Priorité la plus élevée (10)
thread.setPriority(Thread.NORM_PRIORITY); // Priorité par défaut (5)
thread.setPriority(Thread.MIN_PRIORITY);  // Priorité la plus basse (1)

Interruption de thread

Exemple

thread.interrupt(); // Interrompre le thread

// Vérifier l'état d'interruption dans le thread
if (Thread.interrupted()) {
    // Gérer la logique d'interruption
}

Synchronisation des threads

Lorsque plusieurs threads accèdent à des ressources partagées, des mécanismes de synchronisation doivent être utilisés pour éviter des problèmes d'incohérence des données.

Utilisation du mot-clé synchronized

Exemple

class Counter {
    private int count = 0;
   
    public synchronized void increment() {
        count++;
    }
}

Utilisation de l'interface Lock

Exemple

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Counter {
    private int count = 0;
    private Lock lock = new ReentrantLock();
   
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

Pool de threads et classe Thread

En développement réel, les pools de threads sont généralement utilisés pour gérer les threads plutôt que de créer directement des objets Thread.

Exemple

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
       
        for (int i = 0; i < 10; i++) {
            executor.execute(() -> {
                System.out.println("Thread executing task");
            });
        }
       
        executor.shutdown();
    }
}

Bonnes pratiques

  1. Préférez créer des threads en implémentant l'interface Runnable
  2. Utilisez des pools de threads pour gérer les ressources des threads
  3. Évitez la synchronisation excessive ; n'utilisez des mécanismes de synchronisation que lorsque c'est nécessaire
  4. Utilisez le mot-clé volatile pour garantir la visibilité des variables
  5. Envisagez d'utiliser les classes utilitaires avancées du package de concurrence Java (java.util.concurrent)

En faisant un usage raisonnable de la classe Thread et des outils de concurrence associés, vous pouvez écrire des programmes Java multi-threadés efficaces et fiables.

Autres extensions