Computing">
[Go to site: main page, start]

0% ont trouvé ce document utile (0 vote)
3 vues13 pages

Java Multithreading

Le document traite du parallélisme en Java, en expliquant son importance pour améliorer les performances et la réactivité des applications. Il décrit les avantages des threads, les méthodes de création de threads, ainsi que les concepts de synchronisation et de gestion des ressources partagées. Enfin, il aborde des notions avancées comme les sémaphores, les priorités de threads et les threads démon.

Transféré par

Yassmine Saidani
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
3 vues13 pages

Java Multithreading

Le document traite du parallélisme en Java, en expliquant son importance pour améliorer les performances et la réactivité des applications. Il décrit les avantages des threads, les méthodes de création de threads, ainsi que les concepts de synchronisation et de gestion des ressources partagées. Enfin, il aborde des notions avancées comme les sémaphores, les priorités de threads et les threads démon.

Transféré par

Yassmine Saidani
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

M INIM AL

Le Parallélisme en
Java
MiniMax Agent · Mai 2026
LE PARALLÉLISME EN JAVA Mai 2026

Pourquoi utiliser le parallélisme ?

Le parallélisme répond à un besoin aussi bien naturel qu'informatique :

• Nécessité naturelle et quotidienne : Tout comme nous respirons en marchant ou


conduisons en écoutant de la musique, nous avons besoin que nos ordinateurs
effectuent plusieurs tâches simultanément.
• Amélioration des performances : Il permet d'accroître la vitesse de traitement en
répartissant les différentes tâches sur plusieurs processeurs ou cœurs physiques.
• Optimisation des temps d'attente : Le parallélisme permet de profiter des temps de
pause d'une tâche (comme l'attente d'une saisie utilisateur ou d'une entrée/sortie) pour
faire avancer une autre activité au lieu de laisser le processeur inactif.
• Réactivité accrue : Il permet aux applications de rester fluides ; par exemple, une
interface graphique peut continuer de répondre à l'utilisateur pendant qu'une tâche
longue, comme le chargement d'une image, s'exécute en arrière-plan.

Les avantages des threads

Les threads (ou processus légers) sont souvent préférés aux processus classiques pour
plusieurs raisons :

• Partage de mémoire : Contrairement aux processus qui ont des espaces mémoires
isolés, les threads d'un même processus partagent le même espace mémoire, ce qui
facilite la communication et le partage de données.
• Légèreté et économie de ressources : Ils sont beaucoup moins gourmands en
ressources mémoire que les processus.
• Performances accrues : Ils offrent de meilleures performances, tant au moment de leur
lancement qu'au cours de leur exécution.
• Simplicité d'intégration : En Java, les threads sont intégrés nativement au langage sous
forme d'objets, ce qui rend leur manipulation simple et puissante.
• Gestion efficace des ressources système : Ils sont très pratiques pour gérer les
opérations d'entrées/sorties (I/O) en partageant efficacement les ressources.

Les 2 façons de créer un thread en Java

MiniMax Agent 1
LE PARALLÉLISME EN JAVA Mai 2026

Il existe deux méthodes principales pour mettre en place un fil d'exécution (thread) :

1. Hériter de la classe Thread : On crée une classe fille qui redéfinit (override) la méthode
run().
2. Implémenter l'interface Runnable : On crée une classe qui implémente cette interface (et
donc la méthode run()), puis on passe une instance de cette classe au constructeur
d'un objet Thread.

Différence entre extends Thread et


implements Runnable

La distinction réside principalement dans la structure de l'objet et ses capacités d'héritage :

• extends Thread : Un seul objet joue les deux rôles : il définit le code à exécuter
(méthode run()) et sert de contrôleur pour démarrer le thread.
• implements Runnable : Les rôles sont séparés. Un objet (le Runnable) contient le code
métier, et un second objet (l'instance de Thread) sert de contrôleur pour gérer
l'exécution.

Pourquoi Runnable est souvent préférable ?

• Héritage simple en Java : Comme Java ne permet pas l'héritage multiple, si votre
classe doit déjà hériter d'une autre classe, vous devez utiliser Runnable.
• Partage de données : Il est plus simple de partager des ressources entre plusieurs
threads en utilisant une seule instance de Runnable passée à plusieurs contrôleurs
Thread.

Différence entre start() et run()

Il est crucial de ne pas confondre ces deux méthodes pour obtenir un véritable parallélisme
:

• start() : Cette méthode crée un nouveau fil d'exécution géré par la machine virtuelle
Java. Le code contenu dans run() s'exécute en parallèle du programme principal.

MiniMax Agent 2
LE PARALLÉLISME EN JAVA Mai 2026

• run() : Si vous appelez run() directement, c'est un simple appel de méthode classique.
Le code est exécuté par le thread actuel, et aucun nouveau thread n'est lancé.

Pourquoi on ne peut pas appeler start() deux


fois ?

• Erreur d'état : Si le thread est encore en cours d'exécution lors du deuxième appel, le
système lève une exception de type [Link].
• Action inutile : Si le thread a déjà terminé son exécution, le second appel de start() ne
produira rien.
• Solution : Pour exécuter à nouveau le même code, il est nécessaire de créer un nouvel
objet Thread et de l'associer au Runnable avant de faire un nouveau start().

Les quatre états d'un thread

• État nouveau : C'est l'état initial juste après l'instanciation de l'objet thread. À ce stade,
il est opérationnel mais pas encore actif.
• État exécutable : Le thread passe dans cet état dès que la méthode start() est appelée.
Il y reste tant qu'il n'est pas sorti de sa méthode run().
• État en attente : Le thread n'exécute aucun traitement et ne consomme aucune
ressource CPU.
• État mort : La fin définitive de l'exécution du thread.

Quand un thread passe-t-il en état d'attente ?

• Mise en sommeil volontaire : Par l'appel de la méthode [Link](ms).


• Attente de notification : Par l'appel de la méthode wait(), souvent utilisé pour la
synchronisation entre threads.
• Attente d'une ressource : Lorsqu'il tente d'accéder à une ressource bloquante (comme
un flux d'entrée/sortie I/O ou une base de données).
• Concurrence (Verrou) : Lorsqu'il essaie d'accéder à une instance ou une méthode sur
laquelle un verrou a déjà été posé par un autre thread (bloc synchronized).

MiniMax Agent 3
LE PARALLÉLISME EN JAVA Mai 2026

• Attente d'un autre thread : Par l'appel de la méthode join(), le thread courant attend
qu'un autre thread termine son travail.
• Suspension : Par l'appel de la méthode suspend() (bien que cette méthode soit notée
comme obsolète dans les pratiques modernes).

Quand devient-il mort ?

• Fin naturelle : Lorsqu'il arrive à la fin du code contenu dans sa méthode run() et qu'il en
sort normalement.
• Fin subite : Si une exception non interceptée survient, ce qui interrompt brutalement
l'exécution du thread.
Une fois qu'un thread est mort, il ne peut plus être relancé.

Rôles des méthodes importantes

• sleep(long ms) : Méthode statique qui permet d'endormir le thread courant pendant une
durée précise en millisecondes. Le thread ne consomme plus de ressources CPU durant
cette pause.
• join() : Permet de bloquer le thread courant jusqu'à ce qu'un autre thread spécifique ait
terminé son exécution. Indispensable pour synchroniser la fin de plusieurs tâches.
• yield() : Méthode statique qui permet au thread courant de passer la main
volontairement à un autre thread de priorité égale ou supérieure.
• interrupt() : Demande l'interruption d'un thread. Elle positionne un indicateur
"interrompu". Si le thread était en train de dormir ou d'attendre, cela provoque une
exception InterruptedException.
• currentThread() : Méthode statique qui retourne l'objet Thread actuellement en train
d'exécuter le code. Elle permet d'identifier le thread actif à un instant T.

Différence entre sleep() et wait()

Caractéristique sleep() (Classe Thread) wait() (Classe Object)

Origine Méthode de la classe Thread Méthode héritée de la classe Object

MiniMax Agent 4
LE PARALLÉLISME EN JAVA Mai 2026

Communication entre threads


Utilisation Simple pause temporelle
(attente d'une condition)

Ne relâche pas le moniteur s'il Relâche obligatoirement le moniteur


Gestion du verrou
est dans un bloc synchronized de l'objet

Se réveille tout seul après le


Réveil Nécessite notify() ou notifyAll()
délai

Doit être appelé dans une section


Contexte Peut être appelé n'importe où
critique (synchronized)

Pourquoi a-t-on besoin de synchronisation ?

La synchronisation est indispensable dès que plusieurs threads accèdent à des données
partagées. Sans elle, les threads peuvent interférer les uns avec les autres, provoquant des
problèmes d'intégrité et de logique.

Section critique et exclusion mutuelle

• Section critique : Portion de code qui accède à une ressource partagée et qui ne doit
pas être exécutée simultanément par plusieurs threads.
• Exclusion mutuelle : Méthode utilisée pour sécuriser les sections critiques. Elle garantit
que si un thread utilise une variable partagée, tous les autres sont exclus jusqu'à ce que
le premier ait terminé.

Analyse de x = x + 1

Ce code peut donner un résultat faux si deux threads l'exécutent en même temps sur une
variable x = 2. Le problème vient du fait que l'opération n'est pas atomique :

• Lecture : Le thread lit la valeur actuelle de x (ex: 2).


• Calcul : Le thread calcule la nouvelle valeur (2 + 1 = 3).
• Écriture : Le thread enregistre le résultat dans la variable x.

MiniMax Agent 5
LE PARALLÉLISME EN JAVA Mai 2026

Si le Thread 1 et le Thread 2 lisent tous deux la valeur 2 avant d'écrire, le résultat final sera
3 au lieu de 4. C'est ce qu'on appelle une condition de concurrence (race condition).

Le mot-clé synchronized en Java

Le mot-clé synchronized est l'outil principal pour garantir l'exclusion mutuelle. Il repose sur
le concept de moniteur : chaque objet Java possède un verrou unique qui ne peut être
détenu que par un seul thread à la fois.

• Empêche l'exécution simultanée : Il garantit que plusieurs threads ne peuvent pas


exécuter en même temps des sections critiques sur un même objet.
• Gestion automatique du moniteur : Le thread acquiert le moniteur automatiquement en
entrant et le rend en le quittant.
• Réentrance : Un thread qui possède déjà le moniteur peut entrer dans d'autres
méthodes synchronisées de ce même objet sans être bloqué.

Méthode synchronisée vs Bloc synchronisé

Type Syntaxe Portée et Verrou

Synchronise toute la méthode. Le


Méthode public synchronized void m() {
verrou est posé sur l'objet courant
synchronisée ... }
(this).

Synchronise uniquement une portion


Bloc synchronisé synchronized(o) { ... } de code spécifique. On peut choisir
l'objet o qui servira de verrou.

Pourquoi faut-il limiter le code synchronisé ?

• Dégradation des performances : L'exécution de code synchronisé est plus lente car elle
force les threads à attendre leur tour.
• Risques d'interblocage (Deadlock) : Une mauvaise gestion des verrous peut bloquer
l'application entière si deux threads s'attendent mutuellement.

MiniMax Agent 6
LE PARALLÉLISME EN JAVA Mai 2026

• Principe de portée minimale : Il faut synchroniser le moins de code possible pour


permettre au maximum de threads de travailler en parallèle.

Mini Fiche : Le Verrouillage en Java

• Verrou (Moniteur) : Un seul par objet, un seul thread à la fois.


• Static synchronized : Le moniteur de la classe est bloqué, et non celui d'une instance.
• Exception : Si une exception survient dans un bloc synchronisé, le verrou est
automatiquement relâché.
• Affectations atomiques : Il est inutile de synchroniser des variables simples de 32 bits
(int ou boolean), car Java garantit que leur lecture/écriture ne peut être interrompue.

Qu'est-ce qu'un moniteur ?

Un moniteur est une structure de synchronisation de haut niveau qui regroupe des
variables partagées et les méthodes qui les manipulent. En Java, chaque objet possède un
moniteur unique qui sert de mécanisme de contrôle pour autoriser ou interdire l'exécution
de code synchronisé.

• Intégrité des données : L'accès simultané sans contrôle créerait des problèmes de
logique et d'intégrité.
• Protection de la ressource : Pendant qu'un thread utilise une ressource partagée via le
moniteur, tous les autres threads qui tentent d'y accéder sont bloqués.
• Libération automatique : Le thread relâche le verrou en quittant le code, qu'il quitte
normalement ou suite à une exception.

wait(), notify() et notifyAll()

• wait() : Le thread se met en attente d'une condition. Il libère immédiatement le moniteur


de l'objet.
• notify() : Réveille un seul thread qui s'était bloqué sur l'objet via un wait().
• notifyAll() : Réveille tous les threads actuellement bloqués en attente sur l'objet.

MiniMax Agent 7
LE PARALLÉLISME EN JAVA Mai 2026

Pourquoi while et pas if ? Entre le moment où un thread est réveillé et le moment où il


réacquiert le moniteur, un autre thread peut avoir modifié la condition. Le while force le
thread à vérifier à nouveau la condition après son réveil.

La notification perdue

Une notification perdue survient lorsqu'un thread appelle notify() alors qu'aucun thread n'est
actuellement en attente (wait()) sur cet objet. Contrairement à d'autres mécanismes
(comme les sémaphores), les notifications Java ne sont pas stockées. Si le signal est
envoyé et que personne n'écoute, il est définitivement perdu.

Qu'est-ce qu'un sémaphore ?

Un sémaphore est un objet de synchronisation constitué d'un entier (compteur) sur lequel
on peut effectuer deux opérations atomiques. Il sert à gérer l'accès à une ou plusieurs
ressources limitées.

• acquire() : Le thread demande une autorisation. Si un permis est disponible, le


compteur diminue et le thread continue. Sinon, il est bloqué.
• release() : Le thread rend une autorisation au sémaphore. Le compteur augmente, ce
qui peut débloquer un autre thread.
• availablePermits() : Retourne le nombre actuel d'autorisations disponibles.

Exemple : Producteurs / Consommateurs

Un thread Producteur génère des données et les place dans un espace de stockage. Un
thread Consommateur récupère ces données pour les traiter. On utilise deux sémaphores :

• Un sémaphore vide (initialisé à la taille du tampon) pour compter les places libres. Le
producteur fait un acquire() avant d'écrire.
• Un sémaphore plein (initialisé à 0) pour compter les messages prêts. Le
consommateur fait un acquire() avant de lire.

MiniMax Agent 8
LE PARALLÉLISME EN JAVA Mai 2026

Sémaphores vs Moniteurs

Caractéristique Sémaphore Moniteur (synchronized)

Repose sur un compteur


Structure Repose sur un verrou implicite
d'entiers

Peut autoriser plusieurs


Capacité Autorise un seul thread à la fois
threads (si permis > 1)

Plus flexible mais moins


Flexibilité Très structuré et intégré à Java
structuré

Gestion de pools de Protection d'une variable unique ou


Cas d'usage
ressources (ex: 3 imprimantes) section critique

La priorité d'un thread

La priorité est un indicateur numérique qui permet d'influencer l'ordonnancement des


threads par le système.

• Attribution : Méthode setPriority(int p) pour définir la priorité d'un thread.


• Comportement : Si plusieurs threads sont en état "prêt", le système choisit celui qui
possède la plus haute priorité.
• Préemption : Si un thread plus prioritaire devient prêt, le système lui donne
immédiatement la main.

Thread démon

Un thread démon est un type de thread particulier dont le rôle est de fournir des services en
arrière-plan aux threads utilisateurs.

• Utilité : Tâches de support comme le ramasse-miettes (garbage collector) ou la gestion


de l'impression.
• Configuration : setDaemon(true) avant le démarrage avec start().
• Arrêt : Un thread démon s'arrête brutalement s'il s'aperçoit qu'il ne reste plus que des
threads démons en cours d'exécution.

MiniMax Agent 9
LE PARALLÉLISME EN JAVA Mai 2026

Thread Utilisateur vs Thread Démon

Caractéristique Thread Utilisateur Thread Démon

Exécute le code principal de Rend service aux threads


Rôle
l'application utilisateurs

La JVM fonctionne tant qu'il La JVM s'arrête dès qu'il ne reste


Arrêt de la JVM
reste des threads utilisateurs plus que des démons

Se termine normalement à la
Fin d'exécution Est tué brutalement par la JVM
fin de sa méthode run()

Qu'est-ce qu'un système distribué ?

Un système distribué est un ensemble de machines distinctes, ne possédant pas de


mémoire partagée, mais que l'utilisateur perçoit comme une seule et unique machine
virtuelle.

• Un mécanisme de communication inter-processus (IPC) unique et global.


• Un système de protection et de gestion des processus commun à toutes les machines.
• Un noyau de système d'exploitation et un mécanisme de gestion de mémoire
identiques sur chaque nœud du réseau.

RMI (Remote Method Invocation)

RMI est la solution de Java pour le calcul distribué. Elle permet de manipuler des objets
situés sur des machines différentes aussi simplement que s'ils étaient locaux.

• Véritablement orienté objet : Il transmet des objets complexes directement, sans code
supplémentaire.
• Comportement mobile : Il peut déplacer une logique métier du serveur vers le client.
• Sécurité intégrée : RMI utilise le SecurityManager de Java et un système de "bac à
sable" (sandbox).
• Garbage Collection distribué : RMI nettoie automatiquement les objets sur le serveur
distant lorsqu'ils ne sont plus référencés.

MiniMax Agent 10
LE PARALLÉLISME EN JAVA Mai 2026

RMI vs RPC

• Approche Objet vs Procédurale : Le RPC traditionnel se limite au "plus petit


dénominateur commun", alors que RMI est entièrement orienté objet.
• Localisation : RMI utilise un module spécifique appelé rmiregistry sur le serveur pour
localiser les objets distants.
• Complexité des échanges : RMI permet de passer des objets complets en argument, là
où le RPC classique oblige à décomposer les données en types primitifs.

Problème des lecteurs / rédacteurs

Ce problème concerne le partage d'une ressource commune entre deux types d'utilisateurs
:

• Les lecteurs : Ils consultent le contenu sans le modifier. Ils peuvent accéder au fichier
en parallèle sans risque.
• Les rédacteurs : Ils accèdent au fichier pour le modifier. Ils doivent accéder au fichier
en exclusion mutuelle totale.

Problème du producteur / consommateur

Un thread producteur génère des données tandis qu'un thread consommateur les récupère.
La synchronisation est indispensable pour :

• Éviter que le consommateur ne traite plusieurs fois le même message.


• Éviter qu'il ne rate une valeur si le producteur envoie une nouvelle donnée avant que la
précédente n'ait été lue.
• Garantir qu'une donnée n'est traitée qu'une seule fois.

Pourquoi la synchronisation peut réduire les


performances ?

MiniMax Agent 11
LE PARALLÉLISME EN JAVA Mai 2026

• Blocages entre threads : L'exécution de code synchronisé crée des files d'attente qui
ralentissent l'application.
• Entrave aux optimisations : La présence de blocs synchronisés peut empêcher
certaines optimisations automatiques.
• Goulot d'étranglement : Plus il y a de threads en attente d'un moniteur, plus les
performances chutent.
• Risques d'interblocage : Appeler des méthodes pouvant être redéfinies dans une zone
synchronisée peut provoquer des blocages définitifs (deadlocks).

MiniMax Agent 12

Vous aimerez peut-être aussi