Toute application peut avoir plusieurs processus (instances). Chacun de ces processus peut être affecté soit en tant que thread unique, soit en tant que threads multiples. Nous verrons dans ce tutoriel comment effectuer plusieurs tâches en même temps et en savoir plus sur les threads et la synchronisation entre les threads.
Dans ce tutoriel, nous allons apprendre:
- Qu'est-ce que le fil unique
- Qu'est-ce que le multithreading en Java?
- Cycle de vie des threads en Java
- Synchronisation des threads Java
- Exemple de multithreading Java
Qu'est-ce que le fil unique?
Un seul thread est fondamentalement une unité de traitement légère et la plus petite. Java utilise des threads en utilisant une "Thread Class".
Il existe deux types de thread - thread utilisateur et thread démon (les threads démons sont utilisés lorsque nous voulons nettoyer l'application et sont utilisés en arrière-plan).
Lorsqu'une application démarre pour la première fois, un thread utilisateur est créé. Publiez cela, nous pouvons créer de nombreux threads utilisateur et threads démons.
Exemple de filetage unique:
package demotest;classe publique GuruThread{public static void main (String [] args) {System.out.println ("Single Thread");}}
Avantages du fil unique:
- Réduit la surcharge de l'application car un seul thread s'exécute dans le système
- En outre, cela réduit le coût de maintenance de l'application.
Qu'est-ce que le multithreading en Java?
MULTITHREADING en Java est un processus d'exécution de deux ou plusieurs threads simultanément pour une utilisation maximale du processeur. Les applications multithreads exécutent au moins deux threads simultanément. Par conséquent, il est également connu sous le nom de concurrence en Java. Chaque fil est parallèle les uns aux autres. Les threads multiples n'allouent pas de zone mémoire séparée, ils économisent donc de la mémoire. De plus, le changement de contexte entre les threads prend moins de temps.
Exemple de multi thread:
package demotest;public class GuruThread1 implémente Runnable{public static void main (String [] args) {Thread guruThread1 = nouveau Thread ("Guru1");Thread guruThread2 = nouveau Thread ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Les noms des threads sont les suivants:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@Passer outrepublic void run () {}}
Avantages du multithread:
- Les utilisateurs ne sont pas bloqués car les threads sont indépendants et nous pouvons effectuer plusieurs opérations à la fois
- En tant que tels, les threads sont indépendants, les autres threads ne seront pas affectés si un thread rencontre une exception.
Cycle de vie des threads en Java
Le cycle de vie d'un thread:
Il existe différentes étapes du cycle de vie du fil, comme indiqué dans le diagramme ci-dessus:
- Nouveau
- Exécutable
- Fonctionnement
- Attendre
- Morte
- Nouveau: Dans cette phase, le thread est créé en utilisant la classe "Thread class". Il reste dans cet état jusqu'à ce que le programme démarre le thread. Il est également connu sous le nom de fil né.
- Exécutable: dans cette page, l'instance du thread est appelée avec une méthode de démarrage. Le contrôle de thread est donné au planificateur pour terminer l'exécution. Cela dépend du planificateur, s'il faut exécuter le thread.
- En cours d'exécution: lorsque le thread commence à s'exécuter, l'état passe à l'état "en cours d'exécution". Le planificateur sélectionne un thread dans le pool de threads et commence à s'exécuter dans l'application.
- En attente: il s'agit de l'état lorsqu'un thread doit attendre. Comme plusieurs threads sont en cours d'exécution dans l'application, une synchronisation entre les threads est nécessaire. Par conséquent, un thread doit attendre, jusqu'à ce que l'autre thread soit exécuté. Par conséquent, cet état est appelé état d'attente.
- Dead: Il s'agit de l'état lorsque le thread est terminé. Le thread est en cours d'exécution et dès qu'il a terminé le traitement, il est en "état mort".
Certaines des méthodes couramment utilisées pour les threads sont:
Méthode | Description |
---|---|
début() | Cette méthode démarre l'exécution du thread et JVM appelle la méthode run () sur le thread. |
Veille (en millisecondes) | Cette méthode rend le thread en veille, par conséquent, l'exécution du thread s'arrêtera pendant les millisecondes fournies et après cela, le thread recommencera à s'exécuter. Cette aide à la synchronisation des threads. |
getName () | Il renvoie le nom du thread. |
setPriority (int newpriority) | Cela change la priorité du thread. |
rendement () | Cela provoque l'arrêt du thread actuel et l'exécution d'autres threads. |
Exemple: Dans cet exemple, nous allons créer un thread et explorer les méthodes intégrées disponibles pour les threads.
package demotest;La classe publique thread_example1 implémente Runnable {@Passer outrepublic void run () {}public static void main (String [] args) {Thread guruthread1 = nouveau Thread ();guruthread1.start ();essayer {guruthread1.sleep (1000);} catch (InterruptedException e) {// TODO Bloc catch généré automatiquemente.printStackTrace ();}guruthread1.setPriority (1);int gurupriority = guruthread1.getPriority ();System.out.println (gurupriority);System.out.println ("Thread Running");}}
Explication du code:
- Ligne de code 2: Nous créons une classe "thread_Example1" qui implémente l'interface Runnable (elle devrait être implémentée par toute classe dont les instances sont destinées à être exécutées par le thread.)
- Ligne de code 4: elle remplace la méthode d'exécution de l'interface exécutable car il est obligatoire de remplacer cette méthode
- Ligne de code 6: Ici, nous avons défini la méthode principale dans laquelle nous allons démarrer l'exécution du thread.
- Ligne de code 7: Ici, nous créons un nouveau nom de thread comme "guruthread1" en instanciant une nouvelle classe de thread.
- Ligne de code 8: nous utiliserons la méthode "start" du thread en utilisant l'instance "guruthread1". Ici, le thread commencera à s'exécuter.
- Ligne de code 10: Ici, nous utilisons la méthode "sleep" du thread en utilisant l'instance "guruthread1". Par conséquent, le thread dormira pendant 1000 millisecondes.
- Code 9-14: Ici, nous avons mis la méthode sleep dans le bloc try catch car il y a une exception vérifiée qui se produit c'est-à-dire une exception interrompue.
- Ligne de code 15: Ici, nous définissons la priorité du thread sur 1 à partir de la priorité qu'il était
- Ligne de code 16: Ici, nous obtenons la priorité du thread en utilisant getPriority ()
- Ligne de code 17: Ici, nous imprimons la valeur extraite de getPriority
- Ligne de code 18: Ici, nous écrivons un texte que le thread est en cours d'exécution.
Lorsque vous exécutez le code ci-dessus, vous obtenez la sortie suivante:
Production:
5 est la priorité de Thread, et Thread Running est le texte qui est la sortie de notre code.
Synchronisation des threads Java
En multithreading, il y a le comportement asynchrone des programmes. Si un thread écrit des données et un autre thread qui lit des données en même temps, cela peut créer une incohérence dans l'application.
Lorsqu'il est nécessaire d'accéder aux ressources partagées par deux ou plusieurs threads, une approche de synchronisation est utilisée.
Java a fourni des méthodes synchronisées pour implémenter un comportement synchronisé.
Dans cette approche, une fois que le thread atteint l'intérieur du bloc synchronisé, aucun autre thread ne peut appeler cette méthode sur le même objet. Tous les threads doivent attendre que ce thread termine le bloc synchronisé et en ressorte.
De cette façon, la synchronisation aide dans une application multithread. Un thread doit attendre que l'autre thread termine son exécution seulement alors les autres threads sont autorisés à s'exécuter.
Il peut être écrit sous la forme suivante:
Synchronisé (objet){// Bloc d'instructions à synchroniser}
Exemple de multithreading Java
Dans cet exemple, nous allons prendre deux threads et récupérer les noms du thread.
Exemple 1:
GuruThread1.javapackage demotest;La classe publique GuruThread1 implémente Runnable {/ *** @param args* /public static void main (String [] args) {Thread guruThread1 = nouveau Thread ("Guru1");Thread guruThread2 = nouveau Thread ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Les noms des threads sont les suivants:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@Passer outrepublic void run () {}}
Explication du code:
- Ligne de code 3: Nous avons pris une classe "GuruThread1" qui implémente Runnable (elle devrait être implémentée par toute classe dont les instances sont destinées à être exécutées par le thread.)
- Ligne de code 8: C'est la méthode principale de la classe
- Ligne de code 9: Ici, nous instancions la classe Thread et créons une instance nommée "guruThread1" et créons un thread.
- Ligne de code 10: Ici, nous instancions la classe Thread et créons une instance nommée "guruThread2" et créons un thread.
- Ligne de code 11: Nous commençons le fil, c'est-à-dire guruThread1.
- Ligne de code 12: Nous commençons le fil, c'est-à-dire guruThread2.
- Ligne de code 13: sortie du texte sous la forme "Les noms des threads sont les suivants:"
- Ligne de code 14: Obtention du nom du thread 1 à l'aide de la méthode getName () de la classe de thread.
- Ligne de code 15: Obtention du nom du thread 2 à l'aide de la méthode getName () de la classe de thread.
Lorsque vous exécutez le code ci-dessus, vous obtenez la sortie suivante:
Production:
Les noms de threads sont affichés ici sous la forme
- Guru1
- Guru2
Exemple 2:
Dans cet exemple, nous allons apprendre à remplacer les méthodes run () et start () d'une interface exécutable et créer deux threads de cette classe et les exécuter en conséquence.
De plus, nous prenons deux cours,
- Celui qui implémentera l'interface exécutable et
- Un autre qui aura la méthode principale et s'exécutera en conséquence.
package demotest;public class GuruThread2 {public static void main (String [] args) {// TODO Stub de méthode généré automatiquementGuruThread3 threadguru1 = nouveau GuruThread3 ("guru1");threadguru1.start ();GuruThread3 threadguru2 = nouveau GuruThread3 ("guru2");threadguru2.start ();}}La classe GuruThread3 implémente Runnable {Thread guruthread;guruname String privé;GuruThread3 (nom de chaîne) {guruname = nom;}@Passer outrepublic void run () {System.out.println ("Thread en cours d'exécution" + guruname);pour (int i = 0; i <4; i ++) {System.out.println (i);System.out.println (guruname);essayer {Thread.sleep (1000);} catch (InterruptedException e) {System.out.println ("Le thread a été interrompu");}}}public void start () {System.out.println ("Thread démarré");if (guruthread == null) {guruthread = nouveau fil (ceci, guruname);guruthread.start ();}}}
Explication du code:
- Ligne de code 2: Ici, nous prenons une classe "GuruThread2" qui contiendra la méthode principale.
- Ligne de code 4: Ici, nous prenons une méthode principale de la classe.
- Ligne de code 6-7: Ici, nous créons une instance de la classe GuruThread3 (qui est créée dans les lignes ci-dessous du code) en tant que "threadguru1" et nous démarrons le thread.
- Ligne de code 8-9: Ici, nous créons une autre instance de la classe GuruThread3 (qui est créée dans les lignes ci-dessous du code) en tant que "threadguru2" et nous démarrons le thread.
- Ligne de code 11: Ici, nous créons une classe "GuruThread3" qui implémente l'interface exécutable (elle devrait être implémentée par toute classe dont les instances sont destinées à être exécutées par le thread.)
- Ligne de code 13-14: nous prenons deux variables de classe dont l'une est du type thread class et l'autre de la classe string.
- Ligne de code 15-18: nous remplaçons le constructeur GuruThread3, qui prend un argument comme type de chaîne (qui est le nom du thread) qui est assigné à la variable de classe guruname et donc le nom du thread est stocké.
- Ligne de code 20: Ici, nous remplaçons la méthode run () de l'interface exécutable.
- Ligne de code 21: Nous sortons le nom du thread à l'aide de l'instruction println.
- Ligne de code 22-31: Ici, nous utilisons une boucle for avec un compteur initialisé à 0, et il ne devrait pas être inférieur à 4 (nous pouvons prendre n'importe quel nombre, donc ici la boucle s'exécutera 4 fois) et incrémenter le compteur. Nous imprimons le nom du thread et faisons également dormir le thread pendant 1000 millisecondes dans un bloc try-catch lorsque la méthode de sommeil a déclenché une exception vérifiée.
- Ligne de code 33: Ici, nous remplaçons la méthode de démarrage de l'interface exécutable.
- Ligne de code 35: Nous sortons le texte "Thread started".
- Ligne de code 36-40: Ici, nous prenons une condition if pour vérifier si la variable de classe guruthread a une valeur ou non. Si sa valeur est nulle, nous créons une instance en utilisant la classe de thread qui prend le nom comme paramètre (valeur pour laquelle a été assignée dans le constructeur). Après quoi, le thread est démarré en utilisant la méthode start ().
Lorsque vous exécutez le code ci-dessus, vous obtenez la sortie suivante:
Sortie :
Il y a deux threads par conséquent, nous obtenons deux fois le message "Thread started".
Nous obtenons les noms des threads tels que nous les avons générés.
Il entre dans la boucle for où nous imprimons le compteur et le nom du thread et le compteur commence par 0.
La boucle s'exécute trois fois et entre les deux, le thread est mis en veille pendant 1000 millisecondes.
Par conséquent, tout d'abord, nous obtenons guru1 puis guru2 puis à nouveau guru2 car le thread dort ici pendant 1000 millisecondes et ensuite guru1 et à nouveau guru1, le thread dort pendant 1000 millisecondes, donc nous obtenons guru2 puis guru1.
Résumé :
Dans ce didacticiel, nous avons vu les applications multithreads en Java et comment utiliser des threads uniques et multiples.
- En multithreading, les utilisateurs ne sont pas bloqués car les threads sont indépendants et peuvent effectuer plusieurs opérations à la fois
- Les différentes étapes du cycle de vie du fil sont,
- Nouveau
- Exécutable
- Fonctionnement
- Attendre
- Morte
- Nous avons également appris la synchronisation entre les threads, qui aident l'application à fonctionner correctement.
- Le multithreading facilite de nombreuses autres tâches d'application.