Java >> Tutoriel Java >  >> Java

Tutoriel Java Multithreading pour débutants

Salutations les amis, dans cet article nous allons vous expliquer le multithreading Java avec des exemples. Nous couvrirons également les avantages et les inconvénients du threading en Java et explorerons également le cycle de vie du thread.

Après cela, nous donnerons un aperçu de la classe thread et de ses méthodes. Et, enfin, vous saurez comment créer des threads à l'aide de la classe Thread et de l'interface Runnable.

De plus, nous avons complété les concepts de thread à l'aide d'exemples classiques et d'exemples de code. Maintenant, avant d'aller plus loin, apprenons la signification générique d'un processus et d'un fil .

Que signifie un processus en informatique ?

Un processus est constitué d'un espace mémoire alloué par le système d'exploitation pouvant contenir un ou plusieurs threads. Le thread ne peut pas exister seul; cela doit faire partie d'un processus. Un processus reste en cours d'exécution jusqu'à ce que tous les threads non démons aient fini de s'exécuter.

Que signifie un fil  en informatique  ?

  • Le thread est un sous-processus léger et la plus petite unité d'exécution.
  • Chaque thread a un chemin d'exécution distinct.
  • Il partage la zone mémoire du processus.

Commençons maintenant et explorons le monde du multithreading.

Tutoriel Java Multithreading

Qu'est-ce que le multithreading en Java ?

  • Le multithreading Java permet l'exécution simultanée de plusieurs threads.
  • Il permet à un processus d'exécuter ses tâches en mode parallèle sur un système à processeur unique.

Maintenant, une question que vous pouvez vous poser est celle qui a rendu ce concept si célèbre. Pour plus de clarté, voyons quelques-uns des avantages de l'utilisation du multithreading.

Quels sont les avantages et les inconvénients du multithreading Java ?

Avantages :

  • Meilleure utilisation des ressources système.
  • Exécution parallèle des tâches et donc moins de temps d'exécution
  • Performances améliorées sur les machines multiprocesseurs
  • Amélioration de la réactivité de l'interface graphique
  • Threads indépendants (n'affectent pas les autres threads du même processus si une exception se produit)

Le multithreading ne donne pas toujours des avantages. Cela vient aussi avec ses inconvénients. Passons en revue quelques-uns des résultats typiques après.

Inconvénients :

  • Cela entraîne une complexité accrue du code.
  • La synchronisation des ressources partagées (objets, données) est gourmande en CPU/mémoire.
  • Le débogage est difficile car parfois vous ne pouvez pas prédire les résultats.
  • Possibilité accrue d'occurrence de blocage.
  • "Famine" certains fils de discussion peuvent ne pas être diffusés en raison d'une mauvaise conception.

Qu'est-ce que le cycle de vie des threads en Java ?

Avant de passer à la création d'un thread, nous verrons d'abord les différentes phases par lesquelles le thread doit passer pour terminer sa durée de vie.

  • Nouveau
  • Exécutable
  • Courir
  • Non exécutable (bloqué)
  • Terminé

Nouveau-  Un thread est à l'état Nouveau lorsque vous créez l'instance de la classe de thread, mais la méthode start() n'a pas encore été appelée.

Runnable-  Le thread est exécutable après l'exécution de la méthode start(). À ce stade, il attend que le planificateur de threads l'exécute.

En cours d'exécution-  Un thread sélectionné par le planificateur de threads pour exécution reste dans l'état d'exécution.

Non exécutable (bloqué)-  Dans cet état, le thread reste actif, mais il n'est pas éligible pour s'exécuter. Cela peut être dû à une opération de veille, à l'attente de la fin d'une E/S de fichier ou à l'état verrouillé, etc.

Résilié-  Un thread est dit à l'état terminé lorsque sa méthode Run() se termine.

Jusqu'à présent, vous avez lu les concepts de base du multithreading Java, passons maintenant à apprendre les différentes façons de créer des threads.

Comment créer des threads en Java ?

En Java, nous avons les deux manières suivantes de créer des threads.

  • Étendre la classe Thread, ou
  • Mettre en œuvre l'interface Runnable.

Il est essentiel de savoir que Java a fourni la plupart des fonctionnalités de thread dans la classe Thread. Donc, avant de passer à la partie création de thread, commençons par comprendre les différentes fonctionnalités et méthodes disponibles dans la classe Thread.

Méthodes, utilisation et exemples de classe Java Thread

Java réalise le multithreading via sa classe java.lang.Thread. Pour devenir efficace dans l'écriture du code multithread, vous devez connaître les constructeurs et les méthodes de la classe thread avant de commencer à écrire des programmes multithread en Java.

Liste des constructeurs de classe Thread.

La classe Thread a les huit constructeurs suivants.

Thread() : Il crée un objet Thread avec un nom par défaut.

Thread (nom de la chaîne) : Il crée un objet Thread avec un nom spécifié par l'argument name.

Thread (cible exécutable) : Cette méthode construit Thread avec un paramètre de l'objet Runnable qui définit la méthode run().

Thread (cible exécutable, nom de chaîne) : Cette méthode crée Thread avec un nom et un paramètre d'objet Runnable pour définir la méthode run().

Thread (groupe ThreadGroup, cible exécutable) : Il crée un objet Thread avec un objet Runnable et le groupe auquel il appartient.

Thread (groupe ThreadGroup, cible exécutable, nom de chaîne) : Il crée un objet Thread avec un objet Runnable qui définit la méthode run(), le nom spécifié comme nom et l'objet Thread appartient au ThreadGroup auquel le groupe fait référence.

Thread (groupe de threads, nom de chaîne) : Il crée un thread qui a le nom spécifié et s'associe au ThreadGroup donné comme premier paramètre.

Thread (groupe ThreadGroup, cible exécutable, nom de chaîne, taille de pile longue) : ce constructeur spécifie le paramètre ThreadGroup, la taille de la pile d'appels de méthode du thread.

Méthodes générales pour gérer les Threads.

démarrer() :

Lorsque le programme appelle la méthode start(), un nouveau Thread est créé et le code à l'intérieur de la méthode run() est exécuté dans un nouveau Thread.

exécuter() :

Cette méthode est le point d'entrée du thread.

Voyons un exemple de code qui montre comment utiliser les méthodes start() et run().

  package com.techbeamers.multithreading;
  class MultithreadDemo extends Thread{  
  
  public void run(){  
    System.out.println("My thread is in running state.");  
  }
     
   public static void main(String args[]){  
     MultithreadDemo obj=new MultithreadDemo();   
     obj.start();  
  }  
}
Output:
My thread is in running state.	
Chaîne getName() :

Vous pouvez utiliser cette méthode pour obtenir le nom du fil en cours.

setName(nom de la chaîne) :

Vous pouvez utiliser pour définir le nom du fil.

Au cours d'une session de débogage, c'est utile car nous pouvons distinguer les threads. Par défaut, Java définit également l'étiquette de chaque Thread. Alternativement, vous pouvez également donner un nom au Thread en utilisant le constructeur Thread qui prend le nom comme argument. La méthode setName(String name) peut également mettre à jour le nom du Thread.

Voyons un exemple de code qui montre comment donner un nom au Thread en utilisant le constructeur Thread(String name), la méthode setName(String name) et récupérer ce nom dans la fonction run() en utilisant la méthode getName().

Exemple de code :
package com.techbeamers.multithreading;
class NameMyThread
{
   public static void main (String [] args)
   {
      MyThread mt;
      if (args.length == 0)
          mt = new MyThread ();
      else
          mt = new MyThread (args [0]);
      mt.start ();
   }
}
class MyThread extends Thread
{
   MyThread ()
   {
      // The compiler creates the byte code equivalent of super ();
   }
   MyThread (String name)
   {
      setName (name); // Pass name to Thread superclass
   }
   public void run ()
   {
      System.out.println ("My name is: " + getName ());
   }
}
Exemple de sortie.

Si vous oubliez de fournir un nom lors de l'exécution du code, vous verrez la sortie suivante.

Java NameMyThread
Output:
My name is: Thread-0

Si vous donnez un nom à un fil comme "DemoThread", alors la sortie sera.

Java NameMyThread DemoThread
Output:
 My name is: DemoThread	
Veille (longues millisecondes) :

Il suspend un thread pour la période spécifiée. Si un autre thread interrompt ce thread endormi, il lèvera une InterruptedException. Il est donc suggéré d'inclure la méthode sleep() dans le bloc try. Alternativement, la méthode du code doit inclure InterruptedException dans sa clause throws.

booléen isAlive() :

Il détermine si un thread est toujours en cours d'exécution. La JVM considère qu'un thread est actif immédiatement avant d'appeler la méthode run() du thread, pendant l'exécution de run() du thread et immédiatement après le retour de run().

Pendant cet intervalle, la méthode isAlive() renvoie une "vraie" valeur booléenne. Sinon, il renvoie faux.

Cette méthode est utile dans les situations où un thread doit attendre qu'un autre thread termine sa méthode run().

Consultez l'exemple de code ci-dessous :
package com.techbeamers.multithreading;
  class MyThread extends Thread{  
  
  public void run(){  
    System.out.println("My thread is in running state.");  
  }
  }   
   
   class ThreadSleepDemo{
   public static void main(String args[]){  
   MyThread obj=new MyThread();   
   obj.start(); 
   while(obj.isAlive())
   {
   try
	{
	obj.sleep(10);
     }
   catch(InterruptedException e)
    {
     System.out.println(“Sleeping thread interrupted”);
    }
   System.out.println(“Thread-Sleep Demo Complete”);
   }
  }  
}
Output:
My thread is in running state
Thread-Sleep Demo Complete
join(longs millisecondes) :

Cette méthode est appelée lorsqu'un thread veut attendre qu'un autre thread se termine. Voyons un exemple de code pour le méthode.

Consultez l'exemple de code ci-dessous :
  package com.techbeamers.multithreading;
  class MyThread extends Thread{  
  
  public void run(){  
    System.out.println("My thread is in running state.");  
  }
  }   
   
   class ThreadJoinDemo{
   public static void main(String args[]){  
   MyThread obj=new MyThread();   
   obj.start(); 
   try
	{
	obj.join();
     }
   catch(InterruptedException e)
    {
    }
   System.out.println(“Thread-Join Demo Complete”);
   }
  }  
}
Output:
My thread is in running state
Thread-Join Demo Complete
Définir les types de fils.

Les discussions appartiennent aux deux catégories suivantes.

  • Utilisateur, et
  • démon.

Un thread utilisateur exécute des tâches critiques qui doivent se terminer avant que l'application ne se termine. Cependant, un thread démon effectue une récupération de place et d'autres tâches en arrière-plan. Lorsque le thread de démarrage d'une application (un thread utilisateur) se termine, JVM vérifie si un autre thread utilisateur est en cours d'exécution. S'il y a un thread utilisateur en cours d'exécution, la JVM empêche l'application de se terminer. S'il n'y a pas de thread utilisateur en cours d'exécution, la JVM terminera le programme sans se soucier du thread démon en cours d'exécution.

  • Boolean isDaemon() : vérifie si le thread est un thread démon.
  • setDaemon(booléen b) : marque le thread comme démon ou thread utilisateur. Pour démarrer un thread démon, la méthode setDaemon(Boolean b) doit être appelée avec un argument "true ."
Consultez l'exemple de code ci-dessous :
package com.techbeamers.multithreading;

class DaemonThreadDemo
{
   public static void main (String [] args)
   {
      MyThread mt = new MyThread ();
      mt.setDaemon (true);
      mt.start ();
      try
      {
         Thread.sleep (100);
      }
      catch (InterruptedException e)
      {
      }
   }
}
class MyThread extends Thread
{
   public void run ()
   {
      System.out.println ("Daemon is " + isDaemon ());
   }
}
Output:
Daemon is true
Thread currentThread() :

Il renvoie la référence d'instance du thread en cours d'exécution.

Thread.State getState() :

Il renvoie l'état du thread.

Consultez l'exemple de code ci-dessous :
package com.techbeamers.multithreading;

class ThreadStateTest
{
   public static void main (String [] args)
   {

      Thread currentThread = Thread.currentThread();
      System.out.println(currentThread);

      MyThread mt1 = new MyThread ();
      mt1.setName("MyThread1");
      MyThread mt2 = new MyThread();
      mt1.setName("MyThread2");
      System.out.println("Thread State of MyThread1 before calling start: "+mt1.getState());  
      mt1.start ();
      mt2.start();
      System.out.println("Thread State of MyThread1 in Main method before Sleep: " + mt1.getState());  
      System.out.println("Thread State of MyThread2 in Main method before Sleep: " + mt2.getState());  
      
      try
      {
         Thread.sleep (1000);
      }
      catch (InterruptedException e)
      {
      }
      System.out.println("Thread State of MyThread1 in Main method after Sleep: " + mt1.getState());  
      System.out.println("Thread State of MyThread2 in Main method after Sleep: " + mt2.getState()); 
   }
}
class MyThread extends Thread
{
   public void run ()
   {
      System.out.println ("Run by " + Thread.currentThread().getName());
      try
      {
         Thread.sleep (100);
      }
      catch (InterruptedException e)
      {
      }
      System.out.println("Thread State of: "+ Thread.currentThread().getName()+ " - "+Thread.currentThread().getState()); 
 
      System.out.println("Exit of Thread: " + Thread.currentThread().getName());  

   }
}
Exemple de résultat :
Output:

Thread[main,5,main]
Thread State of MyThread1 before calling start: NEW
Run by MyThread2
Thread State of MyThread1 in Main method before Sleep: RUNNABLE
Run by Thread-1
Thread State of MyThread2 in Main method before Sleep: RUNNABLE
Thread State of: MyThread2 - RUNNABLE
Exit of Thread: MyThread2
Thread State of: Thread-1 - RUNNABLE
Exit of Thread: Thread-1
Thread State of MyThread1 in Main method after Sleep: TERMINATED
Thread State of MyThread2 in Main method after Sleep: TERMINATED
rendement() :

Cette méthode provoque une pause temporaire de l'objet thread en cours d'exécution et permet à d'autres threads de s'exécuter.

Découvrez l'exemple de code ci-dessous :

package com.techbeamers.multithreading;

public class ThreadTest extends Thread 
{ 
    public void run() 
    { 
        System.out.println("In run"); 
        yield(); 
        System.out.println("Leaving run"); 
    } 
    public static void main(String []argv) 
    { 
        (new ThreadTest()).start(); 
    } 
}

Le thread s'arrêtera après avoir imprimé "In Run" en raison de la méthode yield(); puisqu'il n'y a pas d'autre thread à exécuter, ce thread reprendra et affichera "Leaving run".

Output:
In Run 
Leaving Run
entier final getPriority() :

Il renvoie la priorité du thread.

final void setPriority(int priority) :

Cette fonction est utilisée pour changer la priorité d'un thread.

Découvrez l'exemple de code ci-dessous :

package com.techbeamers.multithreading;

public class ThreadDemo {

   public static void main(String[] args) {

   Thread t = Thread.currentThread();
   t.setName("Admin Thread");
   // set thread priority to 1
   t.setPriority(1);
     
   // prints the current thread
   System.out.println("Thread = " + t);
   int priority= t.getPriority();
   System.out.println("Thread priority= " + priority); 
   
   int count = Thread.activeCount();
   System.out.println("currently active threads = " + count);
   }
}
Output:
Thread = Thread[Admin Thread,1,main]
Thread priority= 1
currently active threads = 1
int getId() :

Il renvoie l'identifiant du thread.

interrompre() :

Il interrompt le fil.

boolean isInterrupted() :

teste si le thread a été interrompu et renvoie le drapeau interrompu vrai ou faux.

booléen interrompu() :

La méthode statique interrompu() teste si le thread a été interrompu. Cette méthode renvoie l'indicateur interrompu après avoir défini l'indicateur sur faux s'il est vrai.

Découvrez l'exemple de code ci-dessous :

package com.techbeamers.multithreading;

public class TestThreadInterrupt extends Thread {

 public void run() {
  for (int i = 1; i <= 2; i++) {
   if (Thread.interrupted()) {
    System.out.println("code for interrupted thread");
   } else {
    System.out.println("code for normal thread");
   }

  } //end of for loop  
 }

 public static void main(String args[]) {

  TestThreadInterrupt t1 = new TestThreadInterrupt();
  TestThreadInterrupt t2 = new TestThreadInterrupt();

  t1.start();
  t1.interrupt();

  t2.start();

 }
}
Output:
code for interrupted thread
code for normal thread
code for normal thread
code for normal thread
suspendre() :

Vous pouvez l'utiliser pour suspendre le fil. [obsolète]

reprendre() :

Vous pouvez l'utiliser pour reprendre le fil suspendu. [obsolète]

stop() :

Vous pouvez l'utiliser pour arrêter le fil. [obsolète]

Remarque :Sun a déprécié une variété de méthodes Thread, telles que suspend(), resume() et stop() car elles peuvent bloquer vos programmes ou endommager des objets. Par conséquent, vous ne devez pas les appeler dans votre code.

Nous avons couvert presque tous les domaines importants de la classe Java Thread dans la section ci-dessus, espérons que cela vous aidera. Dans le segment suivant, vous verrez les deux méthodes pour créer des threads en Java.

Méthodes et exemples de création de threads Java

Créer un thread en étendant la classe Thread

Dans ce cas, vous devez suivre les étapes suivantes pour générer un thread dans un programme Java.

  • Ajouter une nouvelle classe qui étend la classe Thread.
  • Cette classe nouvellement créée doit remplacer la méthode Run() qui est le point d'entrée du nouveau thread.
  • Invoque la méthode start() pour initier l'exécution du thread.

Découvrez l'exemple de code ci-dessous :

  package com.techbeamers.multithreading;
  class MultithreadDemo extends Thread{  
  
  public void run(){  
    System.out.println("My thread is in running state.");  
  }
     
   public static void main(String args[]){  
     MultithreadDemo obj=new MultithreadDemo();   
     obj.start();  
  }  
}
Output:
 My thread is in running state

Créer un fil à l'aide de l'interface Runnable

Pour cette approche, vous devez suivre les étapes ci-dessous pour créer un fil.

  • Créez une classe qui fait ce qui suit.
    • Mettre en œuvre l'interface Runnable
    • Fournit l'implémentation de la méthode run()
  • La fonction "run()" est un point d'entrée pour le thread, et elle reste active jusqu'à ce que la fonction "run()" termine son exécution.
  • Une fois que vous avez créé le thread, amenez-le à l'état Running en appelant la méthode start().
    • Remarque : La méthode start() appelle implicitement la méthode run().

Découvrez l'exemple de code ci-dessous :

package com.techbeamers.multithreading;
  class MultithreadDemo implements Runnable{  
  
  public void run(){  
    System.out.println("My thread is in running state.");  
  }
     
   public static void main(String args[]){  
     MultithreadDemo obj=new MultithreadDemo();   
     Thread threadobj = new Thread(obj);
     threadobj.start();  
  }  
}
Output:
 My thread is in running state	

Quiz sur le multithreading – À essayer

Voici un quiz Java multithreading doté de 20 questions intéressantes et stimulantes pour les programmeurs. Jetez un œil :

Quiz sur le multithreading – Java

Télécharger des exemples de code multithreading Java

Il est maintenant temps de télécharger les exemples de projets afin que vous puissiez facilement comprendre les extraits de code multithreading Java spécifiés dans cet article. Veuillez utiliser le lien ci-dessous pour commencer votre téléchargement.

⇓ Télécharger le projet multithreading

Résumé – Java Multithreading

Nous souhaitons que le didacticiel multithreading Java ci-dessus vous ait aidé à franchir une étape supplémentaire sur l'échelle d'apprentissage Java. Dans le prochain article sur la programmation Java, nous donnerons un aperçu des différentes manières d'implémenter la synchronisation dans les applications Java.

Meilleur,

TechBeamers


Balise Java