Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Java

Maîtriser le multithreading Java : Programmation concurrente efficace

Java est un langage de programmation multi-thread, ce qui signifie qu'on peut développer des programmes multi-threads en Java. Un programme multi-thread contient deux parties ou plus qui s'exécutent simultanément, chaque partie gérant une tâche différente au même moment, ce qui permet une utilisation optimale des ressources, surtout sur les ordinateurs multi-cœurs.

Par définition, le multitâche correspond au partage de ressources de traitement (CPU) entre plusieurs processus. Le multi-threading étend cette idée aux applications en subdivisant des opérations spécifiques au sein d'une même application en threads individuels. Chaque thread peut s'exécuter en parallèle. L'OS répartit le temps processeur non seulement entre différentes applications, mais aussi entre chaque thread d'une application.

Le multi-threading permet d'écrire des programmes où plusieurs activités progressent simultanément.

Cycle de vie d'un thread

Un thread traverse plusieurs états au cours de son cycle de vie : naissance, démarrage, exécution, puis terminaison. Le diagramme ci-dessous illustre ce cycle complet.

Maîtriser le multithreading Java : Programmation concurrente efficace

Priorités des threads

Chaque thread Java possède une priorité qui aide l'OS à déterminer l'ordre d'ordonnancement. Les priorités vont de MIN_PRIORITY (1) à MAX_PRIORITY (10). La priorité par défaut est NORM_PRIORITY (5).

Les threads de priorité plus élevée sont théoriquement alloués en premier, mais cela ne garantit pas l'ordre d'exécution et reste très dépendant de la plateforme.

Créer un thread en implémentant Runnable

Si votre classe doit s'exécuter comme un thread, implémentez l'interface Runnable en trois étapes :

Étape 1 : Implémenter run()

La méthode run() est le point d'entrée du thread. Placez-y votre logique métier.

public void run()

Étape 2 : Instancier Thread

Thread(Runnable threadObj, String threadName)

threadObj est une instance implémentant Runnable, threadName nomme le nouveau thread.

Étape 3 : Démarrer avec start()

void start()

Cette méthode invoque run() dans un nouveau thread d'exécution.

Exemple complet

class RunnableDemo implements Runnable {
    private Thread t;
    private String threadName;

    RunnableDemo(String name) {
        threadName = name;
        System.out.println("Création de " + threadName);
    }

    public void run() {
        System.out.println("Exécution de " + threadName);
        try {
            for (int i = 4; i > 0; i--) {
                System.out.println("Thread: " + threadName + ", " + i);
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("Thread " + threadName + " interrompu.");
        }
        System.out.println("Thread " + threadName + " terminé.");
    }

    public void start() {
        System.out.println("Démarrage de " + threadName);
        if (t == null) {
            t = new Thread(this, threadName);
            t.start();
        }
    }
}

public class TestThread {
    public static void main(String[] args) {
        RunnableDemo R1 = new RunnableDemo("Thread-1");
        R1.start();
        RunnableDemo R2 = new RunnableDemo("Thread-2");
        R2.start();
    }
}

Résultat typique

Création de Thread-1
Démarrage de Thread-1
Création de Thread-2
Démarrage de Thread-2
Exécution de Thread-1
Thread: Thread-1, 4
Exécution de Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 terminé.
Thread Thread-2 terminé.

Créer un thread en étendant Thread

Alternative : créer une classe qui étend Thread. Cette approche offre plus de flexibilité grâce aux méthodes de la classe Thread.

Étape 1 : Surcharger run()

public void run()

Étape 2 : Appeler start()

void start()

Exemple

class ThreadDemo extends Thread {
    private Thread t;
    private String threadName;

    ThreadDemo(String name) {
        threadName = name;
        System.out.println("Création de " + threadName);
    }

    public void run() {
        System.out.println("Exécution de " + threadName);
        try {
            for (int i = 4; i > 0; i--) {
                System.out.println("Thread: " + threadName + ", " + i);
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            System.out.println("Thread " + threadName + " interrompu.");
        }
        System.out.println("Thread " + threadName + " terminé.");
    }

    public void start() {
        System.out.println("Démarrage de " + threadName);
        if (t == null) {
            t = new Thread(this, threadName);
            t.start();
        }
    }
}

public class TestThread {
    public static void main(String[] args) {
        ThreadDemo T1 = new ThreadDemo("Thread-1");
        T1.start();
        ThreadDemo T2 = new ThreadDemo("Thread-2");
        T2.start();
    }
}

Méthodes importantes de la classe Thread

N°Méthode et description
1public void start() - Démarre le thread dans un chemin d'exécution séparé, puis invoque run().
2public void run() - Point d'entrée si le thread a été créé avec un Runnable.
3public final void setName(String name) - Change le nom du thread.
4public final void setPriority(int priority) - Définit la priorité (1 à 10).
5public final void setDaemon(boolean on) - Marque le thread comme démon.
6public final void join(long millisec) - Attend la fin d'un autre thread.
7public void interrupt() - Interrompt un thread bloqué.
8public final boolean isAlive() - Retourne true si le thread est vivant.

Méthodes statiques (agissent sur le thread courant) :

N°Méthode et description
1public static void yield() - Cède le processeur aux threads de même priorité.
2public static void sleep(long millisec) - Bloque le thread courant.
3public static boolean holdsLock(Object x) - Vérifie si le thread courant détient le verrou sur l'objet.
4public static Thread currentThread() - Retourne le thread courant.
5public static void dumpStack() - Affiche la pile d'appels (debug).

Exemple d'utilisation

// File Name : DisplayMessage.java
public class DisplayMessage implements Runnable {
    private String message;
    public DisplayMessage(String message) { this.message = message; }
    public void run() { while(true) { System.out.println(message); } }
}

// File Name : GuessANumber.java
public class GuessANumber extends Thread {
    private int number;
    public GuessANumber(int number) { this.number = number; }
    public void run() {
        int counter = 0, guess = 0;
        do {
            guess = (int) (Math.random() * 100 + 1);
            System.out.println(this.getName() + " devine " + guess);
            counter++;
        } while (guess != number);
        System.out.println("** Correct ! " + this.getName() + " en " + counter + " essais.**");
    }
}

// File Name : ThreadClassDemo.java
public class ThreadClassDemo {
    public static void main(String[] args) {
        Runnable hello = new DisplayMessage("Hello");
        Thread thread1 = new Thread(hello);
        thread1.setDaemon(true);
        thread1.setName("hello");
        thread1.start();

        Runnable bye = new DisplayMessage("Goodbye");
        Thread thread2 = new Thread(bye);
        thread2.setPriority(Thread.MIN_PRIORITY);
        thread2.setDaemon(true);
        thread2.start();

        Thread thread3 = new GuessANumber(27);
        thread3.start();
        try { thread3.join(); } catch (InterruptedException e) { }

        Thread thread4 = new GuessANumber(75);
        thread4.start();
        System.out.println("main() se termine...");
    }
}

Concepts avancés du multithreading Java

Pour aller plus loin, maîtrisez ces concepts essentiels :

Java

  1. Maîtriser les opérateurs Java : Types, syntaxe et exemples pratiques
  2. Commentaires Java : Types, utilisation et bonnes pratiques
  3. Maîtriser la boucle for améliorée en Java : Syntaxe, exemples et bonnes pratiques
  4. Maîtriser les chaînes de caractères en Java : Création, méthodes et bonnes pratiques
  5. Maîtriser les interfaces Java : concepts, implémentation et bonnes pratiques
  6. Maîtriser les classes internes anonymes en Java : définition, syntaxe et exemples pratiques
  7. Maîtriser le try-with-resources Java : gestion automatique des ressources expliquée
  8. Annotations Java expliquées : types, placement et exemples pratiques
  9. Assertions Java : guide pratique pour détecter les bugs et assurer la fiabilité du code