Concurrence Java - Présentation

Java est un langage de programmation multi-thread qui signifie que nous pouvons développer un programme multi-thread en utilisant Java. Un programme multithread contient deux ou plusieurs parties qui peuvent s'exécuter simultanément et chaque partie peut gérer une tâche différente en même temps en utilisant de manière optimale les ressources disponibles, en particulier lorsque votre ordinateur dispose de plusieurs processeurs.

Par définition, le multitâche se produit lorsque plusieurs processus partagent des ressources de traitement communes telles qu'un processeur. Le multi-threading étend l'idée du multitâche dans des applications où vous pouvez subdiviser des opérations spécifiques au sein d'une seule application en threads individuels. Chacun des threads peut s'exécuter en parallèle. Le système d'exploitation divise le temps de traitement non seulement entre les différentes applications, mais également entre chaque thread d'une application.

Le multi-threading vous permet d'écrire de manière à ce que plusieurs activités puissent se dérouler simultanément dans le même programme.

Cycle de vie d'un fil

Un fil passe par différentes étapes de son cycle de vie. Par exemple, un thread est né, démarré, s'exécute, puis meurt. Le diagramme suivant montre le cycle de vie complet d'un thread.

Voici les étapes du cycle de vie -

  • New- Un nouveau thread commence son cycle de vie dans le nouvel état. Il reste dans cet état jusqu'à ce que le programme démarre le thread. Il est également appelé unborn thread.

  • Runnable- Après le démarrage d'un thread nouvellement né, le thread devient exécutable. Un thread dans cet état est considéré comme exécutant sa tâche.

  • Waiting- Parfois, un thread passe à l'état d'attente pendant que le thread attend qu'un autre thread exécute une tâche. Un thread revient à l'état exécutable uniquement lorsqu'un autre thread signale au thread en attente de continuer à s'exécuter.

  • Timed Waiting- Un thread exécutable peut entrer dans l'état d'attente chronométré pendant un intervalle de temps spécifié. Un thread dans cet état revient à l'état exécutable lorsque cet intervalle de temps expire ou lorsque l'événement qu'il attend se produit.

  • Terminated (Dead) - Un thread exécutable entre dans l'état terminé lorsqu'il termine sa tâche ou s'arrête autrement.

Priorités des threads

Chaque thread Java a une priorité qui aide le système d'exploitation à déterminer l'ordre dans lequel les threads sont planifiés.

Les priorités des threads Java sont comprises entre MIN_PRIORITY (une constante de 1) et MAX_PRIORITY (une constante de 10). Par défaut, chaque thread a la priorité NORM_PRIORITY (une constante de 5).

Les threads avec une priorité plus élevée sont plus importants pour un programme et doivent se voir allouer du temps processeur avant les threads de priorité inférieure. Cependant, les priorités de thread ne peuvent pas garantir l'ordre dans lequel les threads s'exécutent et dépendent beaucoup de la plate-forme.

Créer un thread en implémentant une interface exécutable

Si votre classe est destinée à être exécutée en tant que thread, vous pouvez y parvenir en implémentant un Runnableinterface. Vous devrez suivre trois étapes de base -

Étape 1

Dans un premier temps, vous devez implémenter une méthode run () fournie par un Runnableinterface. Cette méthode fournit un point d'entrée pour le thread et vous placerez votre logique métier complète dans cette méthode. Voici une syntaxe simple de la méthode run () -

public void run( )

Étape 2

Dans un deuxième temps, vous instanciez un Thread objet utilisant le constructeur suivant -

Thread(Runnable threadObj, String threadName);

Où, threadObj est une instance d'une classe qui implémente leRunnable interface et threadName est le nom donné au nouveau fil.

Étape 3

Une fois qu'un objet Thread est créé, vous pouvez le démarrer en appelant start()méthode, qui exécute un appel à la méthode run (). Voici une syntaxe simple de la méthode start () -

void start();

Example

Voici un exemple qui crée un nouveau thread et commence à l'exécuter -

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

   RunnableDemo(String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      
      try {
      
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  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();
   }   
}

Cela produira le résultat suivant -

Output

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running 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 exiting.
Thread Thread-2 exiting.

Créer un thread en étendant une classe de thread

La deuxième façon de créer un thread est de créer une nouvelle classe qui étend Threadclasse en utilisant les deux étapes simples suivantes. Cette approche offre plus de flexibilité dans la gestion de plusieurs threads créés à l'aide des méthodes disponibles dans la classe Thread.

Étape 1

Vous devrez remplacer run( )méthode disponible dans la classe Thread. Cette méthode fournit un point d'entrée pour le thread et vous placerez votre logique métier complète dans cette méthode. Voici une syntaxe simple de la méthode run () -

public void run( )

Étape 2

Une fois l'objet Thread créé, vous pouvez le démarrer en appelant start()méthode, qui exécute un appel à la méthode run (). Voici une syntaxe simple de la méthode start () -

void start( );

Example

Voici le programme précédent réécrit pour étendre le fil -

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   
   ThreadDemo(String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      
      try {

         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  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();
   }   
}

Cela produira le résultat suivant -

Output

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running 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 exiting.
Thread Thread-2 exiting.