Vous êtes sur la page 1sur 31

Les Threads

Programmation
concurrentielle en JAVA
Pr. Mostafa Saadi 20/21

Programmation concurentielle en
JAVA
Introduction

 Un Thread est un processus qui peut s’exécuter en parallèle.

 Un Thread est un objet de la classe Thread.

 Le thread est lancé par la méthode start.

Programmation concurentielle en
JAVA
Tâche d’un thread
Interface Runnable

OU

Programmation concurentielle en
JAVA
Tâche d’un thread
Interface Runnable (2)

Programmation concurentielle en
JAVA
Tâche d’un thread
Classe Thread

Programmation concurentielle en
JAVA
Cycle de vie d’un thread

Programmation concurentielle en
JAVA
Priorité entre les threads

Programmation concurentielle en
JAVA
Attendre la fin d’exécution des threads
Join

Programmation concurentielle en
JAVA
Attendre la fin d’exécution des threads
Join

Programmation concurentielle en
JAVA
Thread : Runnable et Callable
Runnable
 Runnable est une interface fonctionnelle, elle peut être remplacée par une expression
lambda

 Exemple :

Programmation concurentielle en
JAVA
Thread : Runnable et Callable
Callable
 Callable est très similaire à Runnable. C’est une interface fonctionnelle, elle peut être
remplacée par une expression lambda
 Un objet Runnable ne retourne pas de résultat tandis qu'un objet Callable retourne un résultat.
 Un objet Runnable ne peut pas lever une exception vérifiée tandis qu'un objet Callable peut
lever une exception.
 L'interface Runnable existe depuis Java 1.0 alors que Callable n'a été introduit que dans Java
1.5.
 Exemple :

Programmation concurentielle en
JAVA
L’API : ExecutorService
Introduction
 ExecutorService est un interface définie dans l’API java.util.concurrency.

 Elle fournit une nouvelle façon de haut niveau pour la manipulation des thread.

 Ce n’est pas le développeur qui crée les threads mais l‘ExecutorService.

 ExecutorService gère le cycle de vie des threads créés.

 Executros est une Factory pour créer des instances de ExecutorService.

 A l‘inverse d‘un thread qui se termine une fois la tâche est réalisée, le service
ExecutorService ne s‘arrête pas implicitement, même si les tàches sont réalisées.
Programmation concurentielle en
JAVA
L’API : ExecutorService
La classe Future
Si l’on donne à un thread une tâche Callable, comment faire pour récupérer le résultat de
l'exécution d'un thread sachant qu'on ne sait pas à priori s'il a effectivement terminé son
traitement, s'il a levé une exception ou s'il a été suspendu ?

La classe Future permet d’exploiter le résultat d’un thread, elle contient deux méthodes
importantes dans ce contexte (plus d’autres) :

 Boolean isDone(), teste la terminaison d’un thread, retourne true si le thread a terminé,
a été annulé ou une exception a été levée.

 <T> get (), méthode blocante, après que le thread se termine, retourne le résultat retourné
par la methóde Callable.call

Programmation concurentielle en
JAVA
L’API : ExecutorService
Méthodes (1)
ExecutorService définit plusieurs méthodes, les plus importantes pour nous sont :

 void execute(Runnable command), exécute une tâche Runnable.

 <T> Future<T> submit(Callable<T> task), exécute une tâche Callable.

 Future<?> submit(Runnable task), exécute similaire à execute, mais retourne un


objet Future.

Programmation concurentielle en
JAVA
L’API : ExecutorService
Méthodes (2)

 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks),


exécute une collection de tâches Callable et retourne une liste d’objets Future relatifs aux
tâches exécutées.

 <T> T invokeAny(Collection<? extends Callable<T> > tasks), exécute une


collection de tâches Callable, dès qu’un thread se termine, les autres sont arrêtés et
lerésultat du premier est retourné sous la forme d’un objet Future.

 void shutdown(), permet d’arrêter le service ExecutorService.

Programmation concurentielle en
JAVA
L’API : ExecutorService
Méthodes (3)

Programmation concurentielle en
JAVA
L’API : ExecutorService
La factory Executors
ExecutorService étant une interface, comment faire pour en créer des instances ?

L’API concurrency propose une classe factory Executors, qui propose les méthodes suivantes :

 ExecutorService Executors.newSingleThreadExecutor(), crée un seul thread pour


exécuter une ou plusieurs tâches mais dans l’ordre.

 ExecutorService Executors.newFixedThreadPool(int nbreThreads), crée un nombre


limité de thread pour effectuer les tâches. Les tâches sont mises dans une Queue et exécutées par
le thread qui est libre.

 ExecutorService Executors.newCachedThreadPool(), à chaque besoin, ce service crée


un nouveau thread, s’il y a un thread déjà créé et est disponible, on le réutilise.

Programmation concurentielle en
JAVA
L’API : ExecutorService
La factory Executors

 ScheduledExecutorService Executors.newSingleThreadScheduledExecutor(), crée


un seul thread qui sera lancé dans le future, soit une seule fois après une durée déterminée ou de
manière périodique..

 ScheduledExecutorService Executors.newScheduledThreadPool(int nbreThreads),


crée un pool de thrads qui seront lancés dans le future, soit une seule fois après une durée
déterminée ou de manière périodique..

Programmation concurentielle en
JAVA
ExecutorService
Executors.newSingleThreadExecutor (1)
 Remarquez que le processus java ne s‘arrête pas, les executors doivent être arrêtés
explicitement

Programmation concurentielle en
JAVA
ExecutorService
Executors.newSingleThreadExecutor (2)
 Remarquez que le processus java ne s‘arrête pas, les executors doivent être arrêtés
explicitement

Programmation concurentielle en
JAVA
ExecutorService
Executors.newFixedThreadPool

Programmation concurentielle en
JAVA
ExecutorService
Executors.newCachedThreadPool

Programmation concurentielle en
JAVA
ExecutorService
Executors.newSingleThreadScheduledExecutor (1)

Nous permet de créer un unique thread qui pourra être démarré :

 Une fois après un délai donné « d » : schedule

 Après une délai initial, puis périodiquement après chaque durée « d » :


scheduleAtFixedRate

 Après une délai initial, puis périodiquement après chaque durée « d » calculée à partir de
la fin de l’exécution de la tâche précédente : ScheduleWithFixedDelay

Programmation concurentielle en
JAVA
ExecutorService
Executors.newSingleThreadScheduledExecutor (2)
La méthode schedule est identique à la méthode submit, avec l’option de décaler l’exécution.
Cette méthode s’applique aux Runnables et au Callables.

Programmation concurentielle en
JAVA
ExecutorService
Executors.newSingleThreadScheduledExecutor (3)
La méthode scheduleAtFixedRate permet de lancer une tâche de manière périodique. La
période entre les débuts des exécutions est la même.

Programmation concurentielle en
JAVA
ExecutorService
Executors.newSingleThreadScheduledExecutor (4)
La méthode scheduleWithFixedDelay permet de lancer une tâche de manière périodique. La
période entre le début d’exécution d’une tâche et la fin d’exécution de la tâche précedente est
est la même pour toutes les exécutions.

Programmation concurentielle en
JAVA
La synchronisation des threads
Problème
Etant donné que les threads s’exécutent en parallèle, s’ils manipulent le même objet. Que se
passe-t-il ?

Exécutions :

Pourquoi les deux résultats ne se ressemblent pas ? Et pourquoi le résultat n’est pas 1 2 3 4 5 6
7 8 9 10 ?

Programmation concurentielle en
JAVA
La synchronisation des threads
Solution, partie 1: Classes Atomiques (1)
Les opérateurs ++ et -- ne sont pas thread-safe, pourquoi ? Parce que ces opérateurs ne sont
pas atomiques.

Une opération est dite atomique si elle est exécutée comme étant une seule unité sans
interférence avec un autre thread.

L’API concurrency inclut un ensemble de classes atomiques

des méthodes spécifiques


Chaque classe contient
Programmation concurentielle en
JAVA
La synchronisation des threads
Solution, partie 1: Classes Atomiques (2)

Avec la classe artomique, nous sommes sûr qu’aucune valeur ne sera sautée ou en double,
mais comme même l’ordre reste inconsistant.

Problème : l’incrénmentation se fait en atomique, mais les deux opérations d’incrémentation


et d’affichage non.

Programmation concurentielle en
JAVA
La synchronisation des threads
Solution, partie 2: Synchronisation
Si un bloc est reférencé comme synchronisé, il n’est pas accessible par deux threads en
parallèle, le premier thread le verrouille via un Lock et ne le déverouille une fois qu’il termine
son exécution.

Si l’on souhaite synchroniser tout le corp d’une méthode, on peut définir la méthode comme
étant synchronized.

Programmation concurentielle en
JAVA
La synchronisation des threads

Vecteur et ArrayList sont


deux classes qui sont
presque identiques, la
différence majeure entre
elles est que les méthodes
de Vecteur sont
synchronisées alors que
ArrayList non.

Programmation concurentielle en
JAVA

Vous aimerez peut-être aussi