SlideShare uma empresa Scribd logo
1 de 94
Baixar para ler offline
Programmation concurrente
antislashn.org Java avancé - Programmation concurrente 2 - 2 / 94
Les threads
● Java possède le concept de thread
● la JVM s'appuie sur les threads de l'OS sous-jacent
– ou les simules si OS monotâche
● Permet de créer des applications dont certaines
parties s'exécutent en parallèle
● La JVM possède des threads
● le thread principal => méthode main
● des threads secondaires pour la gestion de la JVM
antislashn.org Java avancé - Programmation concurrente 2 - 3 / 94
Multitâche et threads
● Un thread est un flux de contrôle à l'intérieur d'une
application
Système d'exploitation
Application C
Application B
Machine virtuelle Java
Application A
Thread 1
Thread 2
Thread 3
Variables locales
Variables locales
Variables locales
mémoire de
l'application
antislashn.org Java avancé - Programmation concurrente 2 - 4 / 94
Les threads
● Chaque thread exécute son code indépendamment des autres
threads
● les threads peuvent coopérer entre eux
● Les threads donnent l'illusion d'une exécution simultanée de
plusieurs tâches
● Accès aux données par un thread
● les variables locales des méthodes d'un thread sont différentes pour chaque
thread
● si deux threads exécutent la même méthode, chacun obtient un espace mémoire
séparé pour les variables locales de la méthode
● les objets et variables d'instances peuvent être partagés entre les threads
d'un même programme Java.
● les variables statiques sont automatiquement partagées
antislashn.org Java avancé - Programmation concurrente 2 - 5 / 94
Les threads
● Un thread possède
● un nom
● un identifiant
● une priorité
– Thread.MIN_PRIORITY => 1
– Thread.NORM_PRIORITY => 5
– Thread.MAX_PRIORITY => 10
● le status deamon ou non
● un groupe
● un code à exécuter
– méthode run()
● un état
antislashn.org Java avancé - Programmation concurrente 2 - 6 / 94
Les threads
● La JVM arrête son exécution lorsque :
● la méthode System.exit() est invoquée
ou
● tous les threads sont morts
– si le thread n'est pas un daemon
● les daemons n'empêchent pas la JVM de s'arrêter
antislashn.org Java avancé - Programmation concurrente 2 - 7 / 94
Thread – cycle de vie
antislashn.org Java avancé - Programmation concurrente 2 - 8 / 94
Les thread
● Création d'un thread
● par spécialisation de la classe Thread
– redéfinition de la méthode run()
– lancement par la méthode start() sur l'instance
● par implémentation de l'interface Runnable
– codage de la méthode run()
– passer l'instance de la classe à une instance de Thread
– méthode start() sur l'instance de Thread
antislashn.org Java avancé - Programmation concurrente 2 - 9 / 94
Spécialisation de la classe Thread
public class Task extends Thread {
private int delai;
public Task(int delai, String nom) {
this.delai = delai;
setName(nom);
this.setName(nom);
}
@Override
public void run() {
System.out.format(">>> DEBUT TACHE %s de %d s.n", getName(), delai);
try {
this.sleep(delai * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.format(">>> FIN TACHE %s de %d s.n", getName(), delai);
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 10 / 94
Implémentation de Runnable
class MyRunnable implements Runnable{
@Override
public void run() {
try {
System.out.println("DEBUT THREAD");
Thread.sleep(1_000);
System.out.println("FIN THREAD");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MainRunnable {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new MyRunnable());
t.start();
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 11 / 94
Arrêt d'un thread
● Une partie des méthodes de la classe Thread sont
dépréciées
● stop(), resume(), suspend(), destroy()
● Le thread s'arrête à la fin de sa méthode run()
● La méthode interrupt() positionne un flag demandant
l'interruption
● si le thread n'est pas en attente
● utiliser alors les méthodes
– interrupted() : renvoie le flag et le remet à false
– isInterrupted() : renvoie le flag sans le remettre à false
antislashn.org Java avancé - Programmation concurrente 2 - 12 / 94
Arrêt d'un thread
● Si l'état du thread est RUNNABLE
● interrupted() évalue le flag d'interruption et on
peut stopper la méthode run()
● Si l'état du thread est en attente
● suite à sleep(), join() ou wait()
– il reçoit une InterruptionException
● suite à une attente sur une E/S
– il reçoit un ClosedByInterruptionException
● on peut alors stopper le thread dans le traitement de
l'exception
antislashn.org Java avancé - Programmation concurrente 2 - 13 / 94
Arrêt d'un thread
public class ThreadInterrupt implements Runnable {
private int id;
public ThreadInterrupt(int id){
this.id = id;
}
@Override
public void run() {
int i = 0;
while(!Thread.interrupted()){
System.out.printf("thread id : %d - valeur de la boucle %dn",id,i++ );
//Traitement long
for(long k=1 ; k<1000000 ; k++)
for(long r=1; r<1000 ;r++)
;
}
System.out.printf(">>> FIN EXECUTION thread %d - status :
%bn",id,Thread.currentThread().isInterrupted());
}
}
état RUNNABLE
antislashn.org Java avancé - Programmation concurrente 2 - 14 / 94
Arrêt d'un thread
public class ThreadInterrupt implements Runnable {
private int id;
public ThreadInterrupt(int id){
this.id = id;
}
@Override
public void run() {
int i = 0;
while(!Thread.interrupted()){
System.out.printf("thread id : %d - valeur de la boucle %dn",id,i++ );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.printf(">>> CATCH thread %d - status :
%bn",id,Thread.currentThread().isInterrupted());
Thread.currentThread().interrupt();
}
}
System.out.printf(">>> FIN EXECUTION thread %d - status :
%bn",id,Thread.currentThread().isInterrupted());
}
}
état TIMED_WAITING
antislashn.org Java avancé - Programmation concurrente 2 - 15 / 94
Arrêt d'un thread
public class ThreadInterruptMain {
public static void main(String[] args) {
Thread t1 = new Thread(new ThreadInterrupt(1));
Thread t2 = new Thread(new ThreadInterrupt(2));
t1.start();
t2.start();
Scanner in = new Scanner(System.in);
System.out.println("Entrez le numéro du thread à arrêter : ");
int num = in.nextInt();
switch(num){
case 1:
System.out.printf("Etat du thread t1 : %sn",t1.getState());
t1.interrupt();
break;
case 2:
System.out.printf("Etat du thread t2 : %sn",t2.getState());
t2.interrupt();
break;
}
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 16 / 94
Arrêt d'un thread
● Attente de l'arrêt
● méthode join()
– attend la terminaison d'un thread
– appel bloquant tant que le thread est en vie
● retourne immédiatement si le thread n'est pas en vie
– pas démarré, arrêté
● Redémarrage d'un thread
● un thread mort ne peut pas être redémarré
● une instance de Thread ne peut-être utilisée qu'une
seule fois
– une exception IllegalThreadStateException est levée
antislashn.org Java avancé - Programmation concurrente 2 - 17 / 94
Concurrence
● Dans un environnement monothread
● si il y a écriture d'une valeur dans une variable
● la lecture de la variable renverra la valeur écrite
– si celle-ci n'a pas été modifiée entre temps
● Dans un environnement multithread
● les lectures et écritures peuvent avoir être exécutées
dans des threads différents il n'y a pas de garantie
qu'un thread lise la valeur écrite par un autre thread
antislashn.org Java avancé - Programmation concurrente 2 - 18 / 94
Concurence
● Deux threads incrémentent un variable
● au départ la variable vaut 1
● la valeur attendue après les deux incrémentation est 3
Thread 1
● récupère A dans un registre
● incrémente le registre
Thread 2
● récupère A dans un registre
● incrémente le registre
● transfert du registre en mémoire
A == 1
● transfert du registre en mémoire
A == 2
antislashn.org Java avancé - Programmation concurrente 2 - 19 / 94
Concurrence
● L'accès et l'affectation est garantie en Java sur
tous les types sauf long et double
● Il n'y a pas de garanti qu'un thread ne prenne pas
le contrôle entre 2 opérations atomiques
● Pour que le code soit atomique, il faut que l'objet
soit utilisé comme moniteur
● technique pour synchroniser plusieurs tâches qui
utilisent des ressources partagées
antislashn.org Java avancé - Programmation concurrente 2 - 20 / 94
Concurrence
class Foo{
private int a;
private int b = 2;
public Foo(int val){
a=val;
b=2*a;
}
public void changer(){
a++;
b=2*a;
System.out.printf("%s - a == %d, b ==%dn",
Thread.currentThread().getName(),a,b);
}
}
class ThreadFoo extends Thread{
private Foo foo;
public ThreadFoo(Foo foo){
this.foo = foo;
}
public void run(){
for(int i=0 ; i<10 ; i++)
foo.changer();
}
}
code non atomique
antislashn.org Java avancé - Programmation concurrente 2 - 21 / 94
Concurrence
public class SynchronisationMain {
public static void main(String[] args) {
Foo foo = new Foo(10);
ThreadFoo t0 = new ThreadFoo(foo);
ThreadFoo t1 = new ThreadFoo(foo);
t0.start();
t1.start();
}
}
Thread-1 - a == 12, b == 24
Thread-0 - a == 12, b == 24
Thread-1 - a == 13, b == 26
Thread-1 - a == 15, b == 30
antislashn.org Java avancé - Programmation concurrente 2 - 22 / 94
Concurrence
● Verrou d'exclusion mutuelle
● verrou mutex
● un seul thread peut acquérir un mutex
● si deux threads essaient d’acquérir un verrou, un seul
y parvient
– l'autre thread doit attendre que le premier thread restitue le
verrou pour continuer
antislashn.org Java avancé - Programmation concurrente 2 - 23 / 94
Concurrence
● Le mot clé synchronized permet d'éviter que
plusieurs threads utilisent le même code en même
temps
● Tout objet peut jour le rôle de moniteur
● chaque objet possède un verrou
– si un thread prend le verrou aucun autre ne peut utiliser le
code synchronized marqué par ce verrou
● différentes approches d'utilisation de synchronized
antislashn.org Java avancé - Programmation concurrente 2 - 24 / 94
Concurrence
● Réentrance
● si un thread demande un verrou déjà verrouillé par au
autre thread, le thread demandeur est bloqué
● si un thread tente de prendre un verrou qu'il détient
déjà la requête réussit
● les verrous sont acquis par le thread et non par un
appel
– au verrou est associé un thread propriétaire et un compteur
d'acquisition
– lorsque le compteur passe à zéro le verrou est libéré
antislashn.org Java avancé - Programmation concurrente 2 - 25 / 94
Concurrence
● Synchronisation implicite sur this
● synchronized est placé en tant que modificateur de
méthode
– efficace car toute la méthode est verrouillée
– peut poser un problème de performance si les traitements
sont longs
...
public synchronized void changer(){
a++;
b=2*a;
System.out.printf("%s - a == %d, b == %dn",
Thread.currentThread().getName(),a,b);
}
...
Thread-0 - a == 11, b == 22
Thread-0 - a == 12, b == 24
Thread-1 - a == 13, b == 26
Thread-1 - a == 14, b == 28
Thread-1 - a == 15, b == 30
antislashn.org Java avancé - Programmation concurrente 2 - 26 / 94
Concurrence
● Synchronisation sur bloc de code
● on ne synchronise qu'une partie du code en le
protégeant par synchronized
...
public void changer(){
synchronized (this) {
a++;
b=2*a;
}
System.out.printf("%s - a == %d, b == %dn"
,Thread.currentThread().getName(),a,b);
}
...
antislashn.org Java avancé - Programmation concurrente 2 - 27 / 94
Concurrence
● Synchronisation sur un objet
● le moniteur est alors l'objet
...
private Object monitor = new Object();
...
public void changer(){
synchronized (monitor) {
System.out.printf("DEBUT %s - a == %d, b == %dn",
Thread.currentThread().getName(),a,b);
a++;
b=2*a;
System.out.printf("FIN %s - a == %d, b == %dn",
Thread.currentThread().getName(),a,b);
}
}
...
le moniteur est une instance d'Object
antislashn.org Java avancé - Programmation concurrente 2 - 28 / 94
Concurrence
● Synchronisation de la classe
● permet de protéger les variables statiques d'une
classe
class Foo1 {
private static int a = 0;
static void setA(int a) {
Foo1.a = a;
}
static int getA() {
return a;
}
}
class Foo2 {
void methodFoo2(int a) throws ClassNotFoundException {
synchronized (Class.forName("org.antislashn.formation.Foo1")) {
Foo1.setA(a);
System.out.printf("%s - valeur de a : %dn", Thread.currentThread().getName(), Foo1.getA());
}
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 29 / 94
Synchronisation entre threads
● Pour éviter l'interblocage de threads on utilise les
méthodes wait(), notify(), notifyAll()
● si wait() est invoqué à l'intérieur d'une méthode
synchronisée
– le thread actuel est bloqué et mis en liste d'attente
– le moniteur est déverrouillé
– le thread suspendu sera réveillé par une notification sur le
moniteur
● notify() pour libérer un thread de la liste
● notifyAll() pour libérer tous les threads de la liste
antislashn.org Java avancé - Programmation concurrente 2 - 30 / 94
Concurrence
● Thread : méthodes d'attente et de notification
● wait()
– attend l'arrivée d'une condition
● le thread en cours est mis en attente
● le verrou est libéré, d'autres thread peuvent alors exécuter des
méthodes synchronisées avec le même verrou
– doit être invoquée dans un bloc synchronized
● notify()
– notifie un thread en attente d'une condition
– doit être invoquée dans un bloc synchronized
antislashn.org Java avancé - Programmation concurrente 2 - 31 / 94
Concurrence
● Thread : méthodes d'attente et de notification
● notifyAll()
– notifie tous les threads en attente d'une condition
– doit être invoquée dans un bloc synchronized
● wait(int delay)
– attend l'arrivée d'une condition avec un timeout
● le verrou est libéré
● sleep(int delay)
– provoque une attente
● le verrou n'est pas libéré
● cf. aussi TimeUnit.MILLISECONDS.sleep(int ms)
antislashn.org Java avancé - Programmation concurrente 2 - 32 / 94
Concurrence
● Double verrou
public class DoubleLock {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void foo() throws InterruptedException{
synchronized (lock1) {
synchronized (lock2) {
while(...){
lock2.wait();
}
}
}
}
public void notifier(){
lock2.notify();
}
}
foo() verrouille lock1 tant que lock2.wait()
n'est pas terminé
antislashn.org Java avancé - Programmation concurrente 2 - 33 / 94
Concurrence
● Reportez-vous à l'atelier 1
antislashn.org Java avancé - Programmation concurrente 2 - 34 / 94
Concurrence et collections
● Parcours de collection par itérateur ou boucle type
for-each
● les itérateurs renvoyés les collections synchronisées
ne sont pas conçus pour gérer les modifications
concurrentes
– exception ConcurrentModificationException
– solution : verrouiller la collection pendant le parcours
● certains itérateurs sont cachés
– exemple : appel toString() sur une collection
● itération cachée pour appel de toString() sur chaque élément
antislashn.org Java avancé - Programmation concurrente 2 - 35 / 94
Java 5 – principaux ajouts
● Amélioration des collections synchronisées
● ConcurrentHashMap
● CopyOnWriteArrayList
● Queue
● BlockingQueue
antislashn.org Java avancé - Programmation concurrente 2 - 36 / 94
Java 5 – principaux ajouts
● API de concurrence
● historiquement développée par Doug LEA
● JSR 166
● Ensemble de classes et interfaces
● package java.util.concurrent
● Atomicité
● package java.util.concurrent.atomic
●
AtomicBoolea, AtomicLong, ...
antislashn.org Java avancé - Programmation concurrente 2 - 37 / 94
Java 5 – principaux ajouts
● Les loquets
● CountDownLatch
– permet à un ou plusieurs threads d'attendre qu'un ensemble
d'événements se produise
● FutureTask
– utilisé par le framework Executor
– représente des tâches asynchrones dont on veut exploiter le
résultat
● Semaphore
– contrôle le nombre d'activités pouvant simultanément
accéder à une ressource ou à l'exécution d'une action
– gère un nombre de jetons virtuels
antislashn.org Java avancé - Programmation concurrente 2 - 38 / 94
Java 5 – principaux ajouts
● Les barrières
● permettent de bloquer un groupe de thread jusqu'à ce
qu'un événement survienne
– les loquets ne sont pas réutilisables, les barrières le sont
● CyclicBarrier
– permet à un certains nombre de threads de ce donner
rendez-vous
● les threads invoquent await() lorsqu'ils atteignent la barrière, la
barrière s'ouvre lorsque tous les threads sont arrivés
● Exchanger
– permet à deux threads d'échanger des données
antislashn.org Java avancé - Programmation concurrente 2 - 39 / 94
Lock
● interface Lock
● remplace le bloc synchronized
● peut être utilisé avec des conditions
● lock() : acquisition du verrou
● unlock() : libération du verrou
– idiome : unlock est invoqué dans un bloc finally
lock.lock();
try{
// corps du traitement
}
finally{
lock.unlock();
}
antislashn.org Java avancé - Programmation concurrente 2 - 40 / 94
Lock
● ReentrantLock
● verrou d'exclusion mutuel standard
– le verrou n'est détenu que par un seul thread
● ReentrantReadWriteLock
● expose deux objets Lock
– readLock() renvoie un verrou en lecture
– writeLock() renvoie un verrou en écriture
● permet d'avoir plusieurs consommateurs en lecture
pour un producteur en écriture
– optimisations sur les données accédées souvent en lecture
antislashn.org Java avancé - Programmation concurrente 2 - 41 / 94
Condition
● Une condition est créée par l'instance de Lock
● méthode newCondition()
● L'utilisation des conditions remplace l'utilisation
des méthodes de gestion d'un moniteur Object
● wait(), notify(), notifyAll()
● await() : met le thread propriétaire du lock en
attente
● signal() : réveille le thread en attente suite à un
await()
antislashn.org Java avancé - Programmation concurrente 2 - 42 / 94
Lock et Condition
● Dans l'exemple suivant
● si take() est invoqué sur un buffer vide, le thread est
mis en attente jusqu'à ce que des items soient
disponibles
● de même si put() est invoqué sur un buffer plein, le
thread est mis en attente jusqu'à ce qu'il y ait de la
place pour au moins un item
antislashn.org Java avancé - Programmation concurrente 2 - 43 / 94
Lock et Condition
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition full = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
full.await();
items[putptr] = x;
if (++putptr == items.length)
putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
...
}
libère le verrou
antislashn.org Java avancé - Programmation concurrente 2 - 44 / 94
Lock et Condition
class BoundedBuffer {
...
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length)
takeptr = 0;
--count;
full.signal();
return x;
} finally {
lock.unlock();
}
}
libère le verrou
antislashn.org Java avancé - Programmation concurrente 2 - 45 / 94
Concurrence
● Reportez-vous à l'atelier 2
antislashn.org Java avancé - Programmation concurrente 2 - 46 / 94
Volatile
● Chaque thread possède un cache local
● Le mot clé volatile permet de s'assurer qu'une
variable utilisée par plusieurs thread sera toujours
à jour
● la JVM rafraîchira le contenu de la variable à chaque
fois qu'elle est utilisée
– la variable ne sera pas mise dans le cache local des Threads
● attention : voir la prise en compte de volatil par
l'implémentation de la JVM
antislashn.org Java avancé - Programmation concurrente 2 - 47 / 94
ThreadLocal
● Permet à des threads exécutant le même code
run() de posséder leur propre variable
● ThreadLocal<T> est utilisé comme attribut du thread
– les valeurs sont accessible par get() et set()
● méthodes
– T get() retourne la valeur associé au thread, si pas de
variable pour le thread initialValue() est invoquée
– void set(T) met à jour la variable associée au thread
– T initialValue() est invoqué au premier get() si
aucun set() n'a été appelé
– void remove() retire la valeur associée au thread
antislashn.org Java avancé - Programmation concurrente 2 - 48 / 94
Communication entre threads
● Certains flux Java permettent la communication
entre threads
● un thread sera producteur d'octets ou de char
– classes PipedOutputStream et PipedWriter
● un thread sera consommateur d'octets ou char
– classes PipedInputStream et PipedReader
antislashn.org Java avancé - Programmation concurrente 2 - 49 / 94
Communication entre threads
● Reportez-vous à l'atelier 3
antislashn.org Java avancé - Programmation concurrente 2 - 50 / 94
Tâches
● Planification de tâches par la classe Timer
● toutes les tâches tournent dans un même thread
– schedule() et scheduleAtFixedRate() pour planifier
une tâche
– cancel() pour supprimer les tâches non démarrées
– purge() pour retirer les tâches
● les tâches sont codées dans une classe dérivant de
TimerTask
– run() pour le code de la tâche
antislashn.org Java avancé - Programmation concurrente 2 - 51 / 94
CountDownLatch
● Permet de retarder l'exécution des threads tant
qu'une opération n'est pas terminée
● une fois loquet dans son état terminal ouvert, il ne peut
plus changer d'état
● exemple :
– garanti qu'un calcul ne sera pas lancé tant que toutes les
ressources nécessaires n'auront pas étés initialisées
– garanti qu'un service ne sera pas lancé tant que tous les
services dépendant ne sont pas activés
antislashn.org Java avancé - Programmation concurrente 2 - 52 / 94
CountDownLatch
● La méthode await() permet de bloquer les
threads jusqu'à ce que le loquet soit ouvert
● CountDownLatch(int count) : crée le loquet avec
un certains nombre de tours
● void await() : mise en attente tant que le compteur
n'est pas nul
● void countDown() : décrémente le compteur
● long getCount() : renvoie le compteur
antislashn.org Java avancé - Programmation concurrente 2 - 53 / 94
CountDownLatch
● Exemple d'attente de fin de plusieurs threads
class StopThread extends Thread {
private final CountDownLatch latch;
private long delay;
public StopThread(CountDownLatch latch, long ms) {
this.latch = latch;
this.delay = ms;
}
public void run() {
try {
System.out.printf(">>> START %sn", Thread.currentThread().getName());
Tread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
System.out.printf(">>> END %s countDown==%dn",
Thread.currentThread().getName(), latch.getCount());
}
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 54 / 94
CountDownLatch
● Exemple d'attente de fin de plusieurs threads
(suite)
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
int nbTaches = 5;
CountDownLatch latch = new CountDownLatch(nbTaches);
for(int i=0 ; i< nbTaches ; i++){
StopThread t = new StopThread(latch, 1000);
t.start();
}
latch.await();
System.out.println("FIN DE TOUTES LES TACHES");
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 55 / 94
CountDownLatch
● Reportez vous à l'atelier 4
antislashn.org Java avancé - Programmation concurrente 2 - 56 / 94
CyclicBarrier
● Permet de définir un point d'attente à plusieurs
threads
● la barrière est débloquées lorsque tous les processus
enregistrés ont atteint ce point
● par rapport au loquet
– le loquet est éphémère, une fois ouvert il ne peu plus être
utilisé
– un loquet attend des événements, tandis que une barrière
attends d'autres threads
antislashn.org Java avancé - Programmation concurrente 2 - 57 / 94
CyclicBarrier
● CyclicBarrier(int parts) : création d'une
barrière avec un certain nombre de participants
● CyclicBarrier(int parts,
Runnable barrierAction)
création d'une barrière avec un certain nombre de
participants et lancement d'une action lorsque la
barrière est ouverte
● int await() : permet au thread de s'enregistrer
auprès de la barrière, l'appel est bloquant tant que
les autres threads participants n'ont pas fini
antislashn.org Java avancé - Programmation concurrente 2 - 58 / 94
CyclicBarrier
● Exemple d'attente avant lancement d'un autre
thread
● chaque tâche additionne une ligne d'une matrice
● lorsque toutes les tâches sont finies une addition de
chaque ligne est effectuée
private static int matrix[][] = { { 1 },
{ 2, 2 },
{ 3, 3, 3 },
{ 4, 4, 4, 4 },
{ 5, 5, 5, 5, 5 } };
antislashn.org Java avancé - Programmation concurrente 2 - 59 / 94
CyclicBarrier
● Exemple d'attente avant lancement d'un autre
thread
public static void main(String args[]) {
final int rows = matrix.length;
results = new int[rows];
Runnable merger = new Runnable() {
public void run() {
int sum = 0;
for (int i = 0; i < rows; i++) {
sum += results[i];
}
System.out.println("Results are: " + sum);
}
};
CyclicBarrier barrier = new CyclicBarrier(rows, merger);
for (int i = 0; i < rows; i++) {
new Summer(barrier, i).start();
}
System.out.println("Waiting...");
}
thread a lancer lorsque
toutes les tâches seront
terminées
création de la barrière avec
nombre de tâches et thread
à lancer lorsque la barrière
sera ouverte
antislashn.org Java avancé - Programmation concurrente 2 - 60 / 94
CyclicBarrier
● Exemple d'attente avant lancement d'un autre thread
(suite) private static class Summer extends Thread {
int row;
CyclicBarrier barrier;
Summer(CyclicBarrier barrier, int row) {
this.barrier = barrier;
this.row = row;
}
public void run() {
int columns = matrix[row].length;
int sum = 0;
for (int i = 0; i < columns; i++) {
sum += matrix[row][i];
}
results[row] = sum;
System.out.println("Results for row " + row + " are : " + sum);
try {
barrier.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (BrokenBarrierException ex) {
ex.printStackTrace();
}
}
}
attente des autres participants
antislashn.org Java avancé - Programmation concurrente 2 - 61 / 94
CyclicBarrier
● Reportez-vous à l'atelier 5
antislashn.org Java avancé - Programmation concurrente 2 - 62 / 94
Exchanger
● Exchanger<V> : forme de barrière formée de
deux parties s'échangeant des données
● exemple : un thread remplit un buffer de données,
tandis doit lire un buffer
– les thread échangent alors un buffer plein contre un buffer
vide
● l'échange est provoqué dès que les deux threads
appel la méthode V exchange(V x)
antislashn.org Java avancé - Programmation concurrente 2 - 63 / 94
Exchanger
● Exemple d'échange de String
public class ExchangerTest {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<String>();
ExchangerRunnable exchangerRunnable1 = new ExchangerRunnable(exchanger, "A");
ExchangerRunnable exchangerRunnable2 = new ExchangerRunnable(exchanger, "B");
new Thread(exchangerRunnable1).start();
new Thread(exchangerRunnable2).start();
}
}
création de l'échangeur de String
on passe l'échangeur aux 2 threads
antislashn.org Java avancé - Programmation concurrente 2 - 64 / 94
Exchanger
● Exemple d'échange de String
class ExchangerRunnable implements Runnable{
Exchanger exchanger = null;
Object object = null;
public ExchangerRunnable(Exchanger exchanger, Object object) {
this.exchanger = exchanger;
this.object = object;
}
public void run() {
try {
Object previous = this.object;
this.object = this.exchanger.exchange(this.object);
System.out.println(Thread.currentThread().getName() +
" exchanged " + previous + " for " + this.object);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
appel de l'échange, bloquant jusqu'à ce
que les 2 threads soient près
antislashn.org Java avancé - Programmation concurrente 2 - 65 / 94
Exchanger
● Reportez-vous à l'atelier 6
antislashn.org Java avancé - Programmation concurrente 2 - 66 / 94
Semaphore
● Encapsule un entier
● contrainte de positivité
● opérations d'incrémentation et de décrémentation
atomiques
● Gère un ensemble de jetons virtuels
● le nombre initial de jeton est passé au constructeur de
Semaphore
● acquire() : l'activité prend un jeton, appel bloquant
● release() : l'activité rend le jeton
antislashn.org Java avancé - Programmation concurrente 2 - 67 / 94
Semaphore
● Constructeurs
● Semaphore(int permits, boolean fair) créer
le sémaphore en précisant le nombre de jetons et la
distribution des jetons dans l'ordre des demandes
● Semaphore(int permits) créer le sémaphore en
précisant le nombre de jetons, sans garantie de
distribution dans l'ordre des demandes
– équivalent à Semaphore(int permits,false)
antislashn.org Java avancé - Programmation concurrente 2 - 68 / 94
Semaphore
● Permet d'implémenter des pools de ressources
class BoundedList<T>{
private final List<T> liste;
private final Semaphore semaphore;
public BoundedList(int bound){
this.liste = Collections.synchronizedList(new ArrayList<T>());
this.semaphore = new Semaphore(bound);
}
public boolean add(T item) throws InterruptedException{
semaphore.acquire();
boolean ok = false;
try{
ok = liste.add(item);
return ok;
}
finally{
if(!ok)
semaphore.release();
}
}
...
}
tentative d’acquisition d'un jeton
mise en attente si pas de jeton disponible
antislashn.org Java avancé - Programmation concurrente 2 - 69 / 94
Semaphore
● Permet d'implémenter des pools de ressources
class BoundedList<T>{
private final List<T> liste;
private final Semaphore semaphore;
public BoundedList(int bound){
this.liste = Collections.synchronizedList(new ArrayList<T>());
this.semaphore = new Semaphore(bound);
}
public boolean add(T item) throws InterruptedException{
semaphore.acquire();
boolean ok = false;
try{
ok = liste.add(item);
return ok;
}
finally{
if(!ok)
semaphore.release();
}
}
...
}
tentative d’acquisition d'un jeton
mise en attente si pas de jeton disponible
antislashn.org Java avancé - Programmation concurrente 2 - 70 / 94
Exécution de tâches
● JDK 1.5 met à disposition des exécuteurs de
tâches
● interface Executor : découple les appels de tâche
de leur exécution, en précisant l'utilisation des threads,
leur ordonnancement, …
● interface ExecutorService : gestion des tâches
asynchrones
– permet l'utilisation de méthodes de terminaison de
processus, cf. interface Future
● interface ScheduleExecutorService : gestion de
tâches périodiques
antislashn.org Java avancé - Programmation concurrente 2 - 71 / 94
Exécution de tâches
● Les exemples suivants utilisent la classe
RunnableTask
public class RunnableTask implements Runnable {
private int nbSecondes;
public RunnableTask(int nbSecondes) {
this.nbSecondes = nbSecondes;
}
@Override
public void run() {
System.out.println(">>> START "+Thread.currentThread().getName()+
" pour "+nbSecondes+" s");
try {
Thread.sleep(nbSecondes*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(">>> FIN "+Thread.currentThread().getName());
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 72 / 94
Exécution de tâches
● Exemple sur un seul thread
public class MonoThreadRunnableTaskExecutor {
private List<Runnable> runnables = new ArrayList<>();
private ExecutorService service = Executors.newSingleThreadExecutor();
public void add(Runnable runnable){runnables.add(runnable);}
public void start(){
for(Runnable r : runnables){
service.execute(r);
}
service.shutdown();
}
public static void main(String[] args) {
MonoThreadRunnableTaskExecutor executor = new MonoThreadRunnableTaskExecutor();
executor.add(new RunnableTask(1));
executor.add(new RunnableTask(2));
executor.add(new RunnableTask(4));
executor.add(new RunnableTask(3));
executor.start();
System.out.println("Fin des exécutions");
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 73 / 94
Exécution de tâches
● Résultat de l'exécution des tâches sur un seul
thread
>>> START pool-1-thread-1 pour 1 s
>>> FIN pool-1-thread-1
>>> START pool-1-thread-1 pour 2 s
>>> FIN pool-1-thread-1
>>> START pool-1-thread-1 pour 4 s
>>> FIN pool-1-thread-1
>>> START pool-1-thread-1 pour 3 s
>>> FIN pool-1-thread-1
antislashn.org Java avancé - Programmation concurrente 2 - 74 / 94
Exécution de tâches
● Exemple sur un plusieurs thread
public class MultiThreadRunnableTaskExecutor {
private List<Runnable> runnables = new ArrayList<>();
private ExecutorService service = Executors.newFixedThreadPool(10);
public void add(Runnable runnable){
runnables.add(runnable);
}
public void start(){
for(Runnable r : runnables){
service.execute(r);
}
service.shutdown();
}
public static void main(String[] args) {
MultiThreadRunnableTaskExecutor executor = new MultiThreadRunnableTaskExecutor();
executor.add(new RunnableTask(1));
executor.add(new RunnableTask(2));
executor.add(new RunnableTask(4));
executor.add(new RunnableTask(3));
executor.start();
System.out.println("Fin des exécutions");
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 75 / 94
Exécution de tâches
● Résultat de l'exécution des tâches sur un seul
thread
>>> START pool-1-thread-2 pour 2 s
>>> START pool-1-thread-3 pour 4 s
>>> START pool-1-thread-1 pour 1 s
Fin des exécutions
>>> START pool-1-thread-4 pour 3 s
>>> FIN pool-1-thread-1
>>> FIN pool-1-thread-2
>>> FIN pool-1-thread-4
>>> FIN pool-1-thread-3
antislashn.org Java avancé - Programmation concurrente 2 - 76 / 94
Tâches asynchrones
● Future
● interface représentant le traitement résultat d'un
traitement asynchrone
● instances créées par ExecutorService
● Callable
● permet le retour d'une valeur après l'exécution d'une
tâche
– ce que ne permet pas la méthode run() de Runnable
● le callable est soumis à un exécuteur, le framework
retourne un Future
antislashn.org Java avancé - Programmation concurrente 2 - 77 / 94
Tâches asynchrones
● Exemple de Callable
public class Compteur implements Callable<Long> {
private final long nb;
public Compteur(long nb){
this.nb = nb;
}
@Override
public Long call() throws Exception {
System.out.println(">>> "+Thread.currentThread().getName());
long sum = 0;
for(long i=0; i<nb; i++)
sum+=i;
return sum;
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 78 / 94
Tâches asynchrones
● Exemple d'utilisation de Future
public class CompteurFutureTest {
private static final int NB_THREADS = 50;
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(NB_THREADS);
List<Future<Long>> futures = new ArrayList<Future<Long>>();
for(int i=100 ; i< 120 ; i++){
Callable<Long> callable = new Compteur(i);
Future<Long> future = executor.submit(callable);
futures.add(future);
}
executor.shutdown();
long total = 0;
for(Future<Long> f : futures){
try {
total = f.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("TOTAL = "+total);
}
}
antislashn.org Java avancé - Programmation concurrente 2 - 79 / 94
Tâches asynchrones
● Reportez-vous à l'atelier 7
antislashn.org Java avancé - Programmation concurrente 2 - 80 / 94
Java 6 - ajouts
● Deux types de collections sont ajoutées
● Deque : file à double entrée
– garanti les insertions et suppression efficaces aux deux
extrémités
– implémenté par ArrayDeque et LinkedBlockingDeque
● adaptées au pattern "Vol de tâche"
– le consommateur – producteur utilise une seule file de
tâches partagées par tous les consommateurs
– le vol de tâche utilise un file double par consommateur, un
consommateur ayant épuisé sa file peut voler la tâche à la
fin d'une file double d'un autre
antislashn.org Java avancé - Programmation concurrente 2 - 81 / 94
Java 7 : ajouts
● TransferQueue
● interface modélisant une file d'attente bloquante
– le producteur attend que le consommateur prenne ce qu'il a mis
dans la file
● ThreadLocalRandom
● générateur de nombres aléatoires local à un thread
– évite de partager une instance de Random entre plusieurs threads
● Phaser
● barrière de synchronisation réutilisable et supportant un
nombre de tâches enregistrées pouvant varier durant
l'exécution
antislashn.org Java avancé - Programmation concurrente 2 - 82 / 94
Java 7 : fork/join
● Problème de base : traiter de grandes quantités de
données paquet par paquet
● chaque paquet peut être traiter de manière indépendante
des autres
● chaque paquet peut fournir un résultat partiel
● les résultats partiels sont ensuite fusionnés
● La décomposition en sous tâches peut être
● statique : découpage d'un tableau en sous-tableau
● dynamique : découverte d'une arborescence d'un système
de fichier
– quel volume de tâches à créer ?
antislashn.org Java avancé - Programmation concurrente 2 - 83 / 94
Java 7 : fork/join
● Différentes approches sont envisageables
● traiter les paquets les uns après les autres
● traiter les paquets en parallèle avec un point de
synchronisation type CyclicBarrier
● utiliser le traitement parallèle avec ForkJoinTask
antislashn.org Java avancé - Programmation concurrente 2 - 84 / 94
Java 7 : fork/join
● Deux classes de base
● ForkJoinTask
– modélise une tâche unique qui sera envoyée à une réserve
de threads
– peut générer d'autres tâches du même type qui seront
envoyées à la même réserve de threads
● ForkJoinPool
– gère la réserve de threads
– la réserve reçoit les tâches et le dispatche aux threads
– réserve conçue pour qu'un grand nombre de tâches
élémentaires soit traitées par un nombre restreint de threads
antislashn.org Java avancé - Programmation concurrente 2 - 85 / 94
Java 7 : fork/join
● La machine qui exécute la tâche doit posséder
plusieurs processeurs
● La tâche est récursive
● RecursiveTask : avec renvoi de résultat
● RecursiveAction : sans renvoi de résultat
● Algorithme de base d'utilisation du framework
fork/join :
if (my portion of the work is small enough)
do the work directly
else
split my work into two pieces
invoke the two pieces and wait for the results
antislashn.org Java avancé - Programmation concurrente 2 - 86 / 94
Java 7 : fork/join
● La javadoc précise qu'une tâche élémentaire
● ne doit pas comporter de synchronisation afin d'éviter
les blocages
● ne doivent pas partager de variables
● doivent pouvoir être exécutées rapidement
antislashn.org Java avancé - Programmation concurrente 2 - 87 / 94
Java 7 : fork/join
● La javadoc précise qu'une tâche élémentaire
● ne doit pas comporter de synchronisation afin d'éviter
les blocages
● ne doivent pas partager de variables
● doivent pouvoir être exécutées rapidement
antislashn.org Java avancé - Programmation concurrente 2 - 88 / 94
Java 7 : fork/join
ForkJoinPoolForkJoinPool
Tâche longue
s'occupe du découpage
en sous tâches
Tâche longue
s'occupe du découpage
en sous tâches
lance la tâche
sous-tâche sous-tâche sous-tâche
sous-tâche
sous-tâche
sous-tâche sous-tâche
sous-tâche
fork()
join()
antislashn.org Java avancé - Programmation concurrente 2 - 89 / 94
Java 7 : fork/join
● ForkJoinTask<V>
● V : type résultat
● deux méthodes principales
– join() : retourne le résultat de la tâche (V)
● bloquante tant que que la tâche n'est pas finie
– fork() : lance une autre tâche dans la même réserve de
pool que la tâche courante
● une même tâche ne doit pas appeler plus d'une fois sa méthode
fork()
● spécialisée par RecusiveAction et RecursiveTask<V>
– compute() : méthode exécutée par la tâche
antislashn.org Java avancé - Programmation concurrente 2 - 90 / 94
Java 7 : fork/join
● Reportez-vous à l'atelier 8
antislashn.org Java avancé - Programmation concurrente 2 - 91 / 94
Objets immuables
● La classe doit être déclarée final
● pour éviter la modification d'une instance par héritage
● Tous les champs doivent être déclarés final
● La référence this ne doit jamais être exportée
● pas de return this ;
antislashn.org Java avancé - Programmation concurrente 2 - 92 / 94
Objets immuables
● Les propriétés référençant des objets non
immuables doivent :
● être privées
● ne jamais être exportées
● représenter l'unique référence à l'objet
– faire des copies défensives
antislashn.org Java avancé - Programmation concurrente 2 - 93 / 94
Objets immuables
private final Date theDate;
public MaClasse(Date theDate) {
this.theDate = theDate;
}
@Override
public String toString() {
return theDate.toString();
}
Date d = new Date();
MaClasse c = new MaClasse(d);
d.setYear(98);
System.out.println(c);
cette propriété peut-être exportée
private final Date theDate;
public MaClasse(Date theDate) {
this.theDate = (Date) theDate.clone();
}
copie défensive
antislashn.org Java avancé - Programmation concurrente 2 - 94 / 94
Ressources
● Livres
● Java Threads
– auteurs : Scott Oaks, Henry Wong
– éditeur : O'Reilly
● Programmation concurrente en Java
– auteur : Brian Goetz
– éditeur : PEARSON
● web
● http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
● http://www.oracle.com/technetwork/articles/java/fork-join-422606.html
● http://gee.cs.oswego.edu/dl/papers/fj.pdf
● http://blog.paumard.org/

Mais conteúdo relacionado

Mais procurados

Cours Big Data Chap2
Cours Big Data Chap2Cours Big Data Chap2
Cours Big Data Chap2Amal Abid
 
POO Java Introduction
POO Java IntroductionPOO Java Introduction
POO Java IntroductionMouna Torjmen
 
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)ENSET, Université Hassan II Casablanca
 
Correction examen-java-avancé-1
Correction examen-java-avancé-1Correction examen-java-avancé-1
Correction examen-java-avancé-1vangogue
 
Cours java avance avancé thread arraylist
Cours java avance avancé thread arraylistCours java avance avancé thread arraylist
Cours java avance avancé thread arraylistHoussem Hamrouni
 
Uml 2 pratique de la modélisation
Uml 2  pratique de la modélisationUml 2  pratique de la modélisation
Uml 2 pratique de la modélisationNassim Amine
 
La gestion des exceptions avec Java
La gestion des exceptions avec JavaLa gestion des exceptions avec Java
La gestion des exceptions avec JavaPapa Cheikh Cisse
 
Chp5 - Diagramme d'Etat Transition
Chp5 - Diagramme d'Etat TransitionChp5 - Diagramme d'Etat Transition
Chp5 - Diagramme d'Etat TransitionLilia Sfaxi
 
gestion de magasin vente matériels informatique
gestion de magasin vente matériels informatiquegestion de magasin vente matériels informatique
gestion de magasin vente matériels informatiqueOussama Yoshiki
 

Mais procurados (20)

Cours Big Data Chap2
Cours Big Data Chap2Cours Big Data Chap2
Cours Big Data Chap2
 
Tp java ee.pptx
Tp java ee.pptxTp java ee.pptx
Tp java ee.pptx
 
POO Java Introduction
POO Java IntroductionPOO Java Introduction
POO Java Introduction
 
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
Développement d'un site web jee de e commerce basé sur spring (m.youssfi)
 
Correction examen-java-avancé-1
Correction examen-java-avancé-1Correction examen-java-avancé-1
Correction examen-java-avancé-1
 
Cours java avance avancé thread arraylist
Cours java avance avancé thread arraylistCours java avance avancé thread arraylist
Cours java avance avancé thread arraylist
 
Java RMI
Java RMIJava RMI
Java RMI
 
Support Java Avancé Troisième Partie
Support Java Avancé Troisième PartieSupport Java Avancé Troisième Partie
Support Java Avancé Troisième Partie
 
Support POO Java Deuxième Partie
Support POO Java Deuxième PartieSupport POO Java Deuxième Partie
Support POO Java Deuxième Partie
 
Uml 2 pratique de la modélisation
Uml 2  pratique de la modélisationUml 2  pratique de la modélisation
Uml 2 pratique de la modélisation
 
La gestion des exceptions avec Java
La gestion des exceptions avec JavaLa gestion des exceptions avec Java
La gestion des exceptions avec Java
 
Sécurité des Applications Web avec Json Web Token (JWT)
Sécurité des Applications Web avec Json Web Token (JWT)Sécurité des Applications Web avec Json Web Token (JWT)
Sécurité des Applications Web avec Json Web Token (JWT)
 
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka StreamsTraitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
 
HTML, CSS et Javascript
HTML, CSS et JavascriptHTML, CSS et Javascript
HTML, CSS et Javascript
 
Support de cours entrepise java beans ejb m.youssfi
Support de cours entrepise java beans ejb m.youssfiSupport de cours entrepise java beans ejb m.youssfi
Support de cours entrepise java beans ejb m.youssfi
 
Support programmation orientée aspect mohamed youssfi (aop)
Support programmation orientée aspect mohamed youssfi (aop)Support programmation orientée aspect mohamed youssfi (aop)
Support programmation orientée aspect mohamed youssfi (aop)
 
Support de cours Spring M.youssfi
Support de cours Spring  M.youssfiSupport de cours Spring  M.youssfi
Support de cours Spring M.youssfi
 
Chp5 - Diagramme d'Etat Transition
Chp5 - Diagramme d'Etat TransitionChp5 - Diagramme d'Etat Transition
Chp5 - Diagramme d'Etat Transition
 
gestion de magasin vente matériels informatique
gestion de magasin vente matériels informatiquegestion de magasin vente matériels informatique
gestion de magasin vente matériels informatique
 
Support NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDBSupport NodeJS avec TypeScript Express MongoDB
Support NodeJS avec TypeScript Express MongoDB
 

Semelhante a Java - programmation concurrente

Programmation des Threads en java
Programmation des Threads en javaProgrammation des Threads en java
Programmation des Threads en javaEzéquiel Tsagué
 
Wilfreid K. AGBO et Grégoire J. MONEYENGONO - Java thread
Wilfreid K. AGBO et Grégoire J. MONEYENGONO - Java threadWilfreid K. AGBO et Grégoire J. MONEYENGONO - Java thread
Wilfreid K. AGBO et Grégoire J. MONEYENGONO - Java threadWilfreid AGBO
 
intro-csharp developement master 2 IF APP
intro-csharp developement master 2 IF APPintro-csharp developement master 2 IF APP
intro-csharp developement master 2 IF APPfrwebhelp
 
JavaLesBasespourles debutantset pour vous.pdf
JavaLesBasespourles debutantset pour vous.pdfJavaLesBasespourles debutantset pour vous.pdf
JavaLesBasespourles debutantset pour vous.pdfhindguendouz2000
 
Introduction java
Introduction javaIntroduction java
Introduction javaFouad Root
 
Les secrets de la JVM pour les algos à haute fréquence
Les secrets de la JVM pour les algos à haute fréquenceLes secrets de la JVM pour les algos à haute fréquence
Les secrets de la JVM pour les algos à haute fréquenceOCTO Technology
 
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...fdussert
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovyguest6e3bed
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation GroovyJS Bournival
 
I le langage java d'una manière avancée introduction
I  le langage java d'una manière avancée introductionI  le langage java d'una manière avancée introduction
I le langage java d'una manière avancée introductionsabrine_hamdi
 

Semelhante a Java - programmation concurrente (20)

Programmation des Threads en java
Programmation des Threads en javaProgrammation des Threads en java
Programmation des Threads en java
 
Multithreading
MultithreadingMultithreading
Multithreading
 
synchronization.pdf
synchronization.pdfsynchronization.pdf
synchronization.pdf
 
threads.pdf
threads.pdfthreads.pdf
threads.pdf
 
Threads
ThreadsThreads
Threads
 
java_PAR.pdf
java_PAR.pdfjava_PAR.pdf
java_PAR.pdf
 
Java 9 modules
Java 9    modulesJava 9    modules
Java 9 modules
 
Les Threads.ppt
Les Threads.pptLes Threads.ppt
Les Threads.ppt
 
Wilfreid K. AGBO et Grégoire J. MONEYENGONO - Java thread
Wilfreid K. AGBO et Grégoire J. MONEYENGONO - Java threadWilfreid K. AGBO et Grégoire J. MONEYENGONO - Java thread
Wilfreid K. AGBO et Grégoire J. MONEYENGONO - Java thread
 
intro-csharp developement master 2 IF APP
intro-csharp developement master 2 IF APPintro-csharp developement master 2 IF APP
intro-csharp developement master 2 IF APP
 
les Threads
les  Threadsles  Threads
les Threads
 
JavaLesBasespourles debutantset pour vous.pdf
JavaLesBasespourles debutantset pour vous.pdfJavaLesBasespourles debutantset pour vous.pdf
JavaLesBasespourles debutantset pour vous.pdf
 
Introduction java
Introduction javaIntroduction java
Introduction java
 
Multi threadingJava
Multi threadingJavaMulti threadingJava
Multi threadingJava
 
Les secrets de la JVM pour les algos à haute fréquence
Les secrets de la JVM pour les algos à haute fréquenceLes secrets de la JVM pour les algos à haute fréquence
Les secrets de la JVM pour les algos à haute fréquence
 
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
Atoum, le framework de tests unitaires pour PHP 5.3 simple, moderne et intuit...
 
Vert.x 3
Vert.x 3Vert.x 3
Vert.x 3
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
 
I le langage java d'una manière avancée introduction
I  le langage java d'una manière avancée introductionI  le langage java d'una manière avancée introduction
I le langage java d'una manière avancée introduction
 

Mais de Franck SIMON

Distribuer une librairie via maven
Distribuer une librairie via mavenDistribuer une librairie via maven
Distribuer une librairie via mavenFranck SIMON
 
Java 8 - interfaces
Java 8 - interfacesJava 8 - interfaces
Java 8 - interfacesFranck SIMON
 
Java 8 - collections et stream
Java 8 - collections et streamJava 8 - collections et stream
Java 8 - collections et streamFranck SIMON
 
Gwt jetty et sources de données
Gwt   jetty et sources de donnéesGwt   jetty et sources de données
Gwt jetty et sources de donnéesFranck SIMON
 
Description d'un fichier de prélèvements SEPA minimum
Description d'un fichier de prélèvements SEPA minimumDescription d'un fichier de prélèvements SEPA minimum
Description d'un fichier de prélèvements SEPA minimumFranck SIMON
 
Tomcat and apache httpd training
Tomcat and apache httpd trainingTomcat and apache httpd training
Tomcat and apache httpd trainingFranck SIMON
 
JBoss - chapitre JMX
JBoss - chapitre JMXJBoss - chapitre JMX
JBoss - chapitre JMXFranck SIMON
 
Android Input Method Editor
Android   Input Method EditorAndroid   Input Method Editor
Android Input Method EditorFranck SIMON
 
Architectures distribuées
Architectures distribuéesArchitectures distribuées
Architectures distribuéesFranck SIMON
 
Développement Android
Développement AndroidDéveloppement Android
Développement AndroidFranck SIMON
 
Java scripting api
Java scripting apiJava scripting api
Java scripting apiFranck SIMON
 

Mais de Franck SIMON (17)

Distribuer une librairie via maven
Distribuer une librairie via mavenDistribuer une librairie via maven
Distribuer une librairie via maven
 
Java 8 - lambda
Java 8 - lambdaJava 8 - lambda
Java 8 - lambda
 
Java 8 - interfaces
Java 8 - interfacesJava 8 - interfaces
Java 8 - interfaces
 
Java 8 - DateTime
Java 8 - DateTimeJava 8 - DateTime
Java 8 - DateTime
 
Java 8 - collections et stream
Java 8 - collections et streamJava 8 - collections et stream
Java 8 - collections et stream
 
Gwt jetty et sources de données
Gwt   jetty et sources de donnéesGwt   jetty et sources de données
Gwt jetty et sources de données
 
Description d'un fichier de prélèvements SEPA minimum
Description d'un fichier de prélèvements SEPA minimumDescription d'un fichier de prélèvements SEPA minimum
Description d'un fichier de prélèvements SEPA minimum
 
Tomcat and apache httpd training
Tomcat and apache httpd trainingTomcat and apache httpd training
Tomcat and apache httpd training
 
Android ORMLite
Android   ORMLiteAndroid   ORMLite
Android ORMLite
 
JBoss - chapitre JMX
JBoss - chapitre JMXJBoss - chapitre JMX
JBoss - chapitre JMX
 
Android Input Method Editor
Android   Input Method EditorAndroid   Input Method Editor
Android Input Method Editor
 
Squid
SquidSquid
Squid
 
Architectures distribuées
Architectures distribuéesArchitectures distribuées
Architectures distribuées
 
Android NDK
Android   NDKAndroid   NDK
Android NDK
 
Développement Android
Développement AndroidDéveloppement Android
Développement Android
 
jQuery
jQueryjQuery
jQuery
 
Java scripting api
Java scripting apiJava scripting api
Java scripting api
 

Java - programmation concurrente

  • 2. antislashn.org Java avancé - Programmation concurrente 2 - 2 / 94 Les threads ● Java possède le concept de thread ● la JVM s'appuie sur les threads de l'OS sous-jacent – ou les simules si OS monotâche ● Permet de créer des applications dont certaines parties s'exécutent en parallèle ● La JVM possède des threads ● le thread principal => méthode main ● des threads secondaires pour la gestion de la JVM
  • 3. antislashn.org Java avancé - Programmation concurrente 2 - 3 / 94 Multitâche et threads ● Un thread est un flux de contrôle à l'intérieur d'une application Système d'exploitation Application C Application B Machine virtuelle Java Application A Thread 1 Thread 2 Thread 3 Variables locales Variables locales Variables locales mémoire de l'application
  • 4. antislashn.org Java avancé - Programmation concurrente 2 - 4 / 94 Les threads ● Chaque thread exécute son code indépendamment des autres threads ● les threads peuvent coopérer entre eux ● Les threads donnent l'illusion d'une exécution simultanée de plusieurs tâches ● Accès aux données par un thread ● les variables locales des méthodes d'un thread sont différentes pour chaque thread ● si deux threads exécutent la même méthode, chacun obtient un espace mémoire séparé pour les variables locales de la méthode ● les objets et variables d'instances peuvent être partagés entre les threads d'un même programme Java. ● les variables statiques sont automatiquement partagées
  • 5. antislashn.org Java avancé - Programmation concurrente 2 - 5 / 94 Les threads ● Un thread possède ● un nom ● un identifiant ● une priorité – Thread.MIN_PRIORITY => 1 – Thread.NORM_PRIORITY => 5 – Thread.MAX_PRIORITY => 10 ● le status deamon ou non ● un groupe ● un code à exécuter – méthode run() ● un état
  • 6. antislashn.org Java avancé - Programmation concurrente 2 - 6 / 94 Les threads ● La JVM arrête son exécution lorsque : ● la méthode System.exit() est invoquée ou ● tous les threads sont morts – si le thread n'est pas un daemon ● les daemons n'empêchent pas la JVM de s'arrêter
  • 7. antislashn.org Java avancé - Programmation concurrente 2 - 7 / 94 Thread – cycle de vie
  • 8. antislashn.org Java avancé - Programmation concurrente 2 - 8 / 94 Les thread ● Création d'un thread ● par spécialisation de la classe Thread – redéfinition de la méthode run() – lancement par la méthode start() sur l'instance ● par implémentation de l'interface Runnable – codage de la méthode run() – passer l'instance de la classe à une instance de Thread – méthode start() sur l'instance de Thread
  • 9. antislashn.org Java avancé - Programmation concurrente 2 - 9 / 94 Spécialisation de la classe Thread public class Task extends Thread { private int delai; public Task(int delai, String nom) { this.delai = delai; setName(nom); this.setName(nom); } @Override public void run() { System.out.format(">>> DEBUT TACHE %s de %d s.n", getName(), delai); try { this.sleep(delai * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.format(">>> FIN TACHE %s de %d s.n", getName(), delai); } }
  • 10. antislashn.org Java avancé - Programmation concurrente 2 - 10 / 94 Implémentation de Runnable class MyRunnable implements Runnable{ @Override public void run() { try { System.out.println("DEBUT THREAD"); Thread.sleep(1_000); System.out.println("FIN THREAD"); } catch (InterruptedException e) { e.printStackTrace(); } } } public class MainRunnable { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new MyRunnable()); t.start(); } }
  • 11. antislashn.org Java avancé - Programmation concurrente 2 - 11 / 94 Arrêt d'un thread ● Une partie des méthodes de la classe Thread sont dépréciées ● stop(), resume(), suspend(), destroy() ● Le thread s'arrête à la fin de sa méthode run() ● La méthode interrupt() positionne un flag demandant l'interruption ● si le thread n'est pas en attente ● utiliser alors les méthodes – interrupted() : renvoie le flag et le remet à false – isInterrupted() : renvoie le flag sans le remettre à false
  • 12. antislashn.org Java avancé - Programmation concurrente 2 - 12 / 94 Arrêt d'un thread ● Si l'état du thread est RUNNABLE ● interrupted() évalue le flag d'interruption et on peut stopper la méthode run() ● Si l'état du thread est en attente ● suite à sleep(), join() ou wait() – il reçoit une InterruptionException ● suite à une attente sur une E/S – il reçoit un ClosedByInterruptionException ● on peut alors stopper le thread dans le traitement de l'exception
  • 13. antislashn.org Java avancé - Programmation concurrente 2 - 13 / 94 Arrêt d'un thread public class ThreadInterrupt implements Runnable { private int id; public ThreadInterrupt(int id){ this.id = id; } @Override public void run() { int i = 0; while(!Thread.interrupted()){ System.out.printf("thread id : %d - valeur de la boucle %dn",id,i++ ); //Traitement long for(long k=1 ; k<1000000 ; k++) for(long r=1; r<1000 ;r++) ; } System.out.printf(">>> FIN EXECUTION thread %d - status : %bn",id,Thread.currentThread().isInterrupted()); } } état RUNNABLE
  • 14. antislashn.org Java avancé - Programmation concurrente 2 - 14 / 94 Arrêt d'un thread public class ThreadInterrupt implements Runnable { private int id; public ThreadInterrupt(int id){ this.id = id; } @Override public void run() { int i = 0; while(!Thread.interrupted()){ System.out.printf("thread id : %d - valeur de la boucle %dn",id,i++ ); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.printf(">>> CATCH thread %d - status : %bn",id,Thread.currentThread().isInterrupted()); Thread.currentThread().interrupt(); } } System.out.printf(">>> FIN EXECUTION thread %d - status : %bn",id,Thread.currentThread().isInterrupted()); } } état TIMED_WAITING
  • 15. antislashn.org Java avancé - Programmation concurrente 2 - 15 / 94 Arrêt d'un thread public class ThreadInterruptMain { public static void main(String[] args) { Thread t1 = new Thread(new ThreadInterrupt(1)); Thread t2 = new Thread(new ThreadInterrupt(2)); t1.start(); t2.start(); Scanner in = new Scanner(System.in); System.out.println("Entrez le numéro du thread à arrêter : "); int num = in.nextInt(); switch(num){ case 1: System.out.printf("Etat du thread t1 : %sn",t1.getState()); t1.interrupt(); break; case 2: System.out.printf("Etat du thread t2 : %sn",t2.getState()); t2.interrupt(); break; } } }
  • 16. antislashn.org Java avancé - Programmation concurrente 2 - 16 / 94 Arrêt d'un thread ● Attente de l'arrêt ● méthode join() – attend la terminaison d'un thread – appel bloquant tant que le thread est en vie ● retourne immédiatement si le thread n'est pas en vie – pas démarré, arrêté ● Redémarrage d'un thread ● un thread mort ne peut pas être redémarré ● une instance de Thread ne peut-être utilisée qu'une seule fois – une exception IllegalThreadStateException est levée
  • 17. antislashn.org Java avancé - Programmation concurrente 2 - 17 / 94 Concurrence ● Dans un environnement monothread ● si il y a écriture d'une valeur dans une variable ● la lecture de la variable renverra la valeur écrite – si celle-ci n'a pas été modifiée entre temps ● Dans un environnement multithread ● les lectures et écritures peuvent avoir être exécutées dans des threads différents il n'y a pas de garantie qu'un thread lise la valeur écrite par un autre thread
  • 18. antislashn.org Java avancé - Programmation concurrente 2 - 18 / 94 Concurence ● Deux threads incrémentent un variable ● au départ la variable vaut 1 ● la valeur attendue après les deux incrémentation est 3 Thread 1 ● récupère A dans un registre ● incrémente le registre Thread 2 ● récupère A dans un registre ● incrémente le registre ● transfert du registre en mémoire A == 1 ● transfert du registre en mémoire A == 2
  • 19. antislashn.org Java avancé - Programmation concurrente 2 - 19 / 94 Concurrence ● L'accès et l'affectation est garantie en Java sur tous les types sauf long et double ● Il n'y a pas de garanti qu'un thread ne prenne pas le contrôle entre 2 opérations atomiques ● Pour que le code soit atomique, il faut que l'objet soit utilisé comme moniteur ● technique pour synchroniser plusieurs tâches qui utilisent des ressources partagées
  • 20. antislashn.org Java avancé - Programmation concurrente 2 - 20 / 94 Concurrence class Foo{ private int a; private int b = 2; public Foo(int val){ a=val; b=2*a; } public void changer(){ a++; b=2*a; System.out.printf("%s - a == %d, b ==%dn", Thread.currentThread().getName(),a,b); } } class ThreadFoo extends Thread{ private Foo foo; public ThreadFoo(Foo foo){ this.foo = foo; } public void run(){ for(int i=0 ; i<10 ; i++) foo.changer(); } } code non atomique
  • 21. antislashn.org Java avancé - Programmation concurrente 2 - 21 / 94 Concurrence public class SynchronisationMain { public static void main(String[] args) { Foo foo = new Foo(10); ThreadFoo t0 = new ThreadFoo(foo); ThreadFoo t1 = new ThreadFoo(foo); t0.start(); t1.start(); } } Thread-1 - a == 12, b == 24 Thread-0 - a == 12, b == 24 Thread-1 - a == 13, b == 26 Thread-1 - a == 15, b == 30
  • 22. antislashn.org Java avancé - Programmation concurrente 2 - 22 / 94 Concurrence ● Verrou d'exclusion mutuelle ● verrou mutex ● un seul thread peut acquérir un mutex ● si deux threads essaient d’acquérir un verrou, un seul y parvient – l'autre thread doit attendre que le premier thread restitue le verrou pour continuer
  • 23. antislashn.org Java avancé - Programmation concurrente 2 - 23 / 94 Concurrence ● Le mot clé synchronized permet d'éviter que plusieurs threads utilisent le même code en même temps ● Tout objet peut jour le rôle de moniteur ● chaque objet possède un verrou – si un thread prend le verrou aucun autre ne peut utiliser le code synchronized marqué par ce verrou ● différentes approches d'utilisation de synchronized
  • 24. antislashn.org Java avancé - Programmation concurrente 2 - 24 / 94 Concurrence ● Réentrance ● si un thread demande un verrou déjà verrouillé par au autre thread, le thread demandeur est bloqué ● si un thread tente de prendre un verrou qu'il détient déjà la requête réussit ● les verrous sont acquis par le thread et non par un appel – au verrou est associé un thread propriétaire et un compteur d'acquisition – lorsque le compteur passe à zéro le verrou est libéré
  • 25. antislashn.org Java avancé - Programmation concurrente 2 - 25 / 94 Concurrence ● Synchronisation implicite sur this ● synchronized est placé en tant que modificateur de méthode – efficace car toute la méthode est verrouillée – peut poser un problème de performance si les traitements sont longs ... public synchronized void changer(){ a++; b=2*a; System.out.printf("%s - a == %d, b == %dn", Thread.currentThread().getName(),a,b); } ... Thread-0 - a == 11, b == 22 Thread-0 - a == 12, b == 24 Thread-1 - a == 13, b == 26 Thread-1 - a == 14, b == 28 Thread-1 - a == 15, b == 30
  • 26. antislashn.org Java avancé - Programmation concurrente 2 - 26 / 94 Concurrence ● Synchronisation sur bloc de code ● on ne synchronise qu'une partie du code en le protégeant par synchronized ... public void changer(){ synchronized (this) { a++; b=2*a; } System.out.printf("%s - a == %d, b == %dn" ,Thread.currentThread().getName(),a,b); } ...
  • 27. antislashn.org Java avancé - Programmation concurrente 2 - 27 / 94 Concurrence ● Synchronisation sur un objet ● le moniteur est alors l'objet ... private Object monitor = new Object(); ... public void changer(){ synchronized (monitor) { System.out.printf("DEBUT %s - a == %d, b == %dn", Thread.currentThread().getName(),a,b); a++; b=2*a; System.out.printf("FIN %s - a == %d, b == %dn", Thread.currentThread().getName(),a,b); } } ... le moniteur est une instance d'Object
  • 28. antislashn.org Java avancé - Programmation concurrente 2 - 28 / 94 Concurrence ● Synchronisation de la classe ● permet de protéger les variables statiques d'une classe class Foo1 { private static int a = 0; static void setA(int a) { Foo1.a = a; } static int getA() { return a; } } class Foo2 { void methodFoo2(int a) throws ClassNotFoundException { synchronized (Class.forName("org.antislashn.formation.Foo1")) { Foo1.setA(a); System.out.printf("%s - valeur de a : %dn", Thread.currentThread().getName(), Foo1.getA()); } } }
  • 29. antislashn.org Java avancé - Programmation concurrente 2 - 29 / 94 Synchronisation entre threads ● Pour éviter l'interblocage de threads on utilise les méthodes wait(), notify(), notifyAll() ● si wait() est invoqué à l'intérieur d'une méthode synchronisée – le thread actuel est bloqué et mis en liste d'attente – le moniteur est déverrouillé – le thread suspendu sera réveillé par une notification sur le moniteur ● notify() pour libérer un thread de la liste ● notifyAll() pour libérer tous les threads de la liste
  • 30. antislashn.org Java avancé - Programmation concurrente 2 - 30 / 94 Concurrence ● Thread : méthodes d'attente et de notification ● wait() – attend l'arrivée d'une condition ● le thread en cours est mis en attente ● le verrou est libéré, d'autres thread peuvent alors exécuter des méthodes synchronisées avec le même verrou – doit être invoquée dans un bloc synchronized ● notify() – notifie un thread en attente d'une condition – doit être invoquée dans un bloc synchronized
  • 31. antislashn.org Java avancé - Programmation concurrente 2 - 31 / 94 Concurrence ● Thread : méthodes d'attente et de notification ● notifyAll() – notifie tous les threads en attente d'une condition – doit être invoquée dans un bloc synchronized ● wait(int delay) – attend l'arrivée d'une condition avec un timeout ● le verrou est libéré ● sleep(int delay) – provoque une attente ● le verrou n'est pas libéré ● cf. aussi TimeUnit.MILLISECONDS.sleep(int ms)
  • 32. antislashn.org Java avancé - Programmation concurrente 2 - 32 / 94 Concurrence ● Double verrou public class DoubleLock { private final Object lock1 = new Object(); private final Object lock2 = new Object(); public void foo() throws InterruptedException{ synchronized (lock1) { synchronized (lock2) { while(...){ lock2.wait(); } } } } public void notifier(){ lock2.notify(); } } foo() verrouille lock1 tant que lock2.wait() n'est pas terminé
  • 33. antislashn.org Java avancé - Programmation concurrente 2 - 33 / 94 Concurrence ● Reportez-vous à l'atelier 1
  • 34. antislashn.org Java avancé - Programmation concurrente 2 - 34 / 94 Concurrence et collections ● Parcours de collection par itérateur ou boucle type for-each ● les itérateurs renvoyés les collections synchronisées ne sont pas conçus pour gérer les modifications concurrentes – exception ConcurrentModificationException – solution : verrouiller la collection pendant le parcours ● certains itérateurs sont cachés – exemple : appel toString() sur une collection ● itération cachée pour appel de toString() sur chaque élément
  • 35. antislashn.org Java avancé - Programmation concurrente 2 - 35 / 94 Java 5 – principaux ajouts ● Amélioration des collections synchronisées ● ConcurrentHashMap ● CopyOnWriteArrayList ● Queue ● BlockingQueue
  • 36. antislashn.org Java avancé - Programmation concurrente 2 - 36 / 94 Java 5 – principaux ajouts ● API de concurrence ● historiquement développée par Doug LEA ● JSR 166 ● Ensemble de classes et interfaces ● package java.util.concurrent ● Atomicité ● package java.util.concurrent.atomic ● AtomicBoolea, AtomicLong, ...
  • 37. antislashn.org Java avancé - Programmation concurrente 2 - 37 / 94 Java 5 – principaux ajouts ● Les loquets ● CountDownLatch – permet à un ou plusieurs threads d'attendre qu'un ensemble d'événements se produise ● FutureTask – utilisé par le framework Executor – représente des tâches asynchrones dont on veut exploiter le résultat ● Semaphore – contrôle le nombre d'activités pouvant simultanément accéder à une ressource ou à l'exécution d'une action – gère un nombre de jetons virtuels
  • 38. antislashn.org Java avancé - Programmation concurrente 2 - 38 / 94 Java 5 – principaux ajouts ● Les barrières ● permettent de bloquer un groupe de thread jusqu'à ce qu'un événement survienne – les loquets ne sont pas réutilisables, les barrières le sont ● CyclicBarrier – permet à un certains nombre de threads de ce donner rendez-vous ● les threads invoquent await() lorsqu'ils atteignent la barrière, la barrière s'ouvre lorsque tous les threads sont arrivés ● Exchanger – permet à deux threads d'échanger des données
  • 39. antislashn.org Java avancé - Programmation concurrente 2 - 39 / 94 Lock ● interface Lock ● remplace le bloc synchronized ● peut être utilisé avec des conditions ● lock() : acquisition du verrou ● unlock() : libération du verrou – idiome : unlock est invoqué dans un bloc finally lock.lock(); try{ // corps du traitement } finally{ lock.unlock(); }
  • 40. antislashn.org Java avancé - Programmation concurrente 2 - 40 / 94 Lock ● ReentrantLock ● verrou d'exclusion mutuel standard – le verrou n'est détenu que par un seul thread ● ReentrantReadWriteLock ● expose deux objets Lock – readLock() renvoie un verrou en lecture – writeLock() renvoie un verrou en écriture ● permet d'avoir plusieurs consommateurs en lecture pour un producteur en écriture – optimisations sur les données accédées souvent en lecture
  • 41. antislashn.org Java avancé - Programmation concurrente 2 - 41 / 94 Condition ● Une condition est créée par l'instance de Lock ● méthode newCondition() ● L'utilisation des conditions remplace l'utilisation des méthodes de gestion d'un moniteur Object ● wait(), notify(), notifyAll() ● await() : met le thread propriétaire du lock en attente ● signal() : réveille le thread en attente suite à un await()
  • 42. antislashn.org Java avancé - Programmation concurrente 2 - 42 / 94 Lock et Condition ● Dans l'exemple suivant ● si take() est invoqué sur un buffer vide, le thread est mis en attente jusqu'à ce que des items soient disponibles ● de même si put() est invoqué sur un buffer plein, le thread est mis en attente jusqu'à ce qu'il y ait de la place pour au moins un item
  • 43. antislashn.org Java avancé - Programmation concurrente 2 - 43 / 94 Lock et Condition class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition full = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) full.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } } ... } libère le verrou
  • 44. antislashn.org Java avancé - Programmation concurrente 2 - 44 / 94 Lock et Condition class BoundedBuffer { ... public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; full.signal(); return x; } finally { lock.unlock(); } } libère le verrou
  • 45. antislashn.org Java avancé - Programmation concurrente 2 - 45 / 94 Concurrence ● Reportez-vous à l'atelier 2
  • 46. antislashn.org Java avancé - Programmation concurrente 2 - 46 / 94 Volatile ● Chaque thread possède un cache local ● Le mot clé volatile permet de s'assurer qu'une variable utilisée par plusieurs thread sera toujours à jour ● la JVM rafraîchira le contenu de la variable à chaque fois qu'elle est utilisée – la variable ne sera pas mise dans le cache local des Threads ● attention : voir la prise en compte de volatil par l'implémentation de la JVM
  • 47. antislashn.org Java avancé - Programmation concurrente 2 - 47 / 94 ThreadLocal ● Permet à des threads exécutant le même code run() de posséder leur propre variable ● ThreadLocal<T> est utilisé comme attribut du thread – les valeurs sont accessible par get() et set() ● méthodes – T get() retourne la valeur associé au thread, si pas de variable pour le thread initialValue() est invoquée – void set(T) met à jour la variable associée au thread – T initialValue() est invoqué au premier get() si aucun set() n'a été appelé – void remove() retire la valeur associée au thread
  • 48. antislashn.org Java avancé - Programmation concurrente 2 - 48 / 94 Communication entre threads ● Certains flux Java permettent la communication entre threads ● un thread sera producteur d'octets ou de char – classes PipedOutputStream et PipedWriter ● un thread sera consommateur d'octets ou char – classes PipedInputStream et PipedReader
  • 49. antislashn.org Java avancé - Programmation concurrente 2 - 49 / 94 Communication entre threads ● Reportez-vous à l'atelier 3
  • 50. antislashn.org Java avancé - Programmation concurrente 2 - 50 / 94 Tâches ● Planification de tâches par la classe Timer ● toutes les tâches tournent dans un même thread – schedule() et scheduleAtFixedRate() pour planifier une tâche – cancel() pour supprimer les tâches non démarrées – purge() pour retirer les tâches ● les tâches sont codées dans une classe dérivant de TimerTask – run() pour le code de la tâche
  • 51. antislashn.org Java avancé - Programmation concurrente 2 - 51 / 94 CountDownLatch ● Permet de retarder l'exécution des threads tant qu'une opération n'est pas terminée ● une fois loquet dans son état terminal ouvert, il ne peut plus changer d'état ● exemple : – garanti qu'un calcul ne sera pas lancé tant que toutes les ressources nécessaires n'auront pas étés initialisées – garanti qu'un service ne sera pas lancé tant que tous les services dépendant ne sont pas activés
  • 52. antislashn.org Java avancé - Programmation concurrente 2 - 52 / 94 CountDownLatch ● La méthode await() permet de bloquer les threads jusqu'à ce que le loquet soit ouvert ● CountDownLatch(int count) : crée le loquet avec un certains nombre de tours ● void await() : mise en attente tant que le compteur n'est pas nul ● void countDown() : décrémente le compteur ● long getCount() : renvoie le compteur
  • 53. antislashn.org Java avancé - Programmation concurrente 2 - 53 / 94 CountDownLatch ● Exemple d'attente de fin de plusieurs threads class StopThread extends Thread { private final CountDownLatch latch; private long delay; public StopThread(CountDownLatch latch, long ms) { this.latch = latch; this.delay = ms; } public void run() { try { System.out.printf(">>> START %sn", Thread.currentThread().getName()); Tread.sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } finally { latch.countDown(); System.out.printf(">>> END %s countDown==%dn", Thread.currentThread().getName(), latch.getCount()); } } }
  • 54. antislashn.org Java avancé - Programmation concurrente 2 - 54 / 94 CountDownLatch ● Exemple d'attente de fin de plusieurs threads (suite) public class CountDownLatchTest { public static void main(String[] args) throws InterruptedException { int nbTaches = 5; CountDownLatch latch = new CountDownLatch(nbTaches); for(int i=0 ; i< nbTaches ; i++){ StopThread t = new StopThread(latch, 1000); t.start(); } latch.await(); System.out.println("FIN DE TOUTES LES TACHES"); } }
  • 55. antislashn.org Java avancé - Programmation concurrente 2 - 55 / 94 CountDownLatch ● Reportez vous à l'atelier 4
  • 56. antislashn.org Java avancé - Programmation concurrente 2 - 56 / 94 CyclicBarrier ● Permet de définir un point d'attente à plusieurs threads ● la barrière est débloquées lorsque tous les processus enregistrés ont atteint ce point ● par rapport au loquet – le loquet est éphémère, une fois ouvert il ne peu plus être utilisé – un loquet attend des événements, tandis que une barrière attends d'autres threads
  • 57. antislashn.org Java avancé - Programmation concurrente 2 - 57 / 94 CyclicBarrier ● CyclicBarrier(int parts) : création d'une barrière avec un certain nombre de participants ● CyclicBarrier(int parts, Runnable barrierAction) création d'une barrière avec un certain nombre de participants et lancement d'une action lorsque la barrière est ouverte ● int await() : permet au thread de s'enregistrer auprès de la barrière, l'appel est bloquant tant que les autres threads participants n'ont pas fini
  • 58. antislashn.org Java avancé - Programmation concurrente 2 - 58 / 94 CyclicBarrier ● Exemple d'attente avant lancement d'un autre thread ● chaque tâche additionne une ligne d'une matrice ● lorsque toutes les tâches sont finies une addition de chaque ligne est effectuée private static int matrix[][] = { { 1 }, { 2, 2 }, { 3, 3, 3 }, { 4, 4, 4, 4 }, { 5, 5, 5, 5, 5 } };
  • 59. antislashn.org Java avancé - Programmation concurrente 2 - 59 / 94 CyclicBarrier ● Exemple d'attente avant lancement d'un autre thread public static void main(String args[]) { final int rows = matrix.length; results = new int[rows]; Runnable merger = new Runnable() { public void run() { int sum = 0; for (int i = 0; i < rows; i++) { sum += results[i]; } System.out.println("Results are: " + sum); } }; CyclicBarrier barrier = new CyclicBarrier(rows, merger); for (int i = 0; i < rows; i++) { new Summer(barrier, i).start(); } System.out.println("Waiting..."); } thread a lancer lorsque toutes les tâches seront terminées création de la barrière avec nombre de tâches et thread à lancer lorsque la barrière sera ouverte
  • 60. antislashn.org Java avancé - Programmation concurrente 2 - 60 / 94 CyclicBarrier ● Exemple d'attente avant lancement d'un autre thread (suite) private static class Summer extends Thread { int row; CyclicBarrier barrier; Summer(CyclicBarrier barrier, int row) { this.barrier = barrier; this.row = row; } public void run() { int columns = matrix[row].length; int sum = 0; for (int i = 0; i < columns; i++) { sum += matrix[row][i]; } results[row] = sum; System.out.println("Results for row " + row + " are : " + sum); try { barrier.await(); } catch (InterruptedException ex) { ex.printStackTrace(); } catch (BrokenBarrierException ex) { ex.printStackTrace(); } } } attente des autres participants
  • 61. antislashn.org Java avancé - Programmation concurrente 2 - 61 / 94 CyclicBarrier ● Reportez-vous à l'atelier 5
  • 62. antislashn.org Java avancé - Programmation concurrente 2 - 62 / 94 Exchanger ● Exchanger<V> : forme de barrière formée de deux parties s'échangeant des données ● exemple : un thread remplit un buffer de données, tandis doit lire un buffer – les thread échangent alors un buffer plein contre un buffer vide ● l'échange est provoqué dès que les deux threads appel la méthode V exchange(V x)
  • 63. antislashn.org Java avancé - Programmation concurrente 2 - 63 / 94 Exchanger ● Exemple d'échange de String public class ExchangerTest { public static void main(String[] args) { Exchanger<String> exchanger = new Exchanger<String>(); ExchangerRunnable exchangerRunnable1 = new ExchangerRunnable(exchanger, "A"); ExchangerRunnable exchangerRunnable2 = new ExchangerRunnable(exchanger, "B"); new Thread(exchangerRunnable1).start(); new Thread(exchangerRunnable2).start(); } } création de l'échangeur de String on passe l'échangeur aux 2 threads
  • 64. antislashn.org Java avancé - Programmation concurrente 2 - 64 / 94 Exchanger ● Exemple d'échange de String class ExchangerRunnable implements Runnable{ Exchanger exchanger = null; Object object = null; public ExchangerRunnable(Exchanger exchanger, Object object) { this.exchanger = exchanger; this.object = object; } public void run() { try { Object previous = this.object; this.object = this.exchanger.exchange(this.object); System.out.println(Thread.currentThread().getName() + " exchanged " + previous + " for " + this.object); } catch (InterruptedException e) { e.printStackTrace(); } } } appel de l'échange, bloquant jusqu'à ce que les 2 threads soient près
  • 65. antislashn.org Java avancé - Programmation concurrente 2 - 65 / 94 Exchanger ● Reportez-vous à l'atelier 6
  • 66. antislashn.org Java avancé - Programmation concurrente 2 - 66 / 94 Semaphore ● Encapsule un entier ● contrainte de positivité ● opérations d'incrémentation et de décrémentation atomiques ● Gère un ensemble de jetons virtuels ● le nombre initial de jeton est passé au constructeur de Semaphore ● acquire() : l'activité prend un jeton, appel bloquant ● release() : l'activité rend le jeton
  • 67. antislashn.org Java avancé - Programmation concurrente 2 - 67 / 94 Semaphore ● Constructeurs ● Semaphore(int permits, boolean fair) créer le sémaphore en précisant le nombre de jetons et la distribution des jetons dans l'ordre des demandes ● Semaphore(int permits) créer le sémaphore en précisant le nombre de jetons, sans garantie de distribution dans l'ordre des demandes – équivalent à Semaphore(int permits,false)
  • 68. antislashn.org Java avancé - Programmation concurrente 2 - 68 / 94 Semaphore ● Permet d'implémenter des pools de ressources class BoundedList<T>{ private final List<T> liste; private final Semaphore semaphore; public BoundedList(int bound){ this.liste = Collections.synchronizedList(new ArrayList<T>()); this.semaphore = new Semaphore(bound); } public boolean add(T item) throws InterruptedException{ semaphore.acquire(); boolean ok = false; try{ ok = liste.add(item); return ok; } finally{ if(!ok) semaphore.release(); } } ... } tentative d’acquisition d'un jeton mise en attente si pas de jeton disponible
  • 69. antislashn.org Java avancé - Programmation concurrente 2 - 69 / 94 Semaphore ● Permet d'implémenter des pools de ressources class BoundedList<T>{ private final List<T> liste; private final Semaphore semaphore; public BoundedList(int bound){ this.liste = Collections.synchronizedList(new ArrayList<T>()); this.semaphore = new Semaphore(bound); } public boolean add(T item) throws InterruptedException{ semaphore.acquire(); boolean ok = false; try{ ok = liste.add(item); return ok; } finally{ if(!ok) semaphore.release(); } } ... } tentative d’acquisition d'un jeton mise en attente si pas de jeton disponible
  • 70. antislashn.org Java avancé - Programmation concurrente 2 - 70 / 94 Exécution de tâches ● JDK 1.5 met à disposition des exécuteurs de tâches ● interface Executor : découple les appels de tâche de leur exécution, en précisant l'utilisation des threads, leur ordonnancement, … ● interface ExecutorService : gestion des tâches asynchrones – permet l'utilisation de méthodes de terminaison de processus, cf. interface Future ● interface ScheduleExecutorService : gestion de tâches périodiques
  • 71. antislashn.org Java avancé - Programmation concurrente 2 - 71 / 94 Exécution de tâches ● Les exemples suivants utilisent la classe RunnableTask public class RunnableTask implements Runnable { private int nbSecondes; public RunnableTask(int nbSecondes) { this.nbSecondes = nbSecondes; } @Override public void run() { System.out.println(">>> START "+Thread.currentThread().getName()+ " pour "+nbSecondes+" s"); try { Thread.sleep(nbSecondes*1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(">>> FIN "+Thread.currentThread().getName()); } }
  • 72. antislashn.org Java avancé - Programmation concurrente 2 - 72 / 94 Exécution de tâches ● Exemple sur un seul thread public class MonoThreadRunnableTaskExecutor { private List<Runnable> runnables = new ArrayList<>(); private ExecutorService service = Executors.newSingleThreadExecutor(); public void add(Runnable runnable){runnables.add(runnable);} public void start(){ for(Runnable r : runnables){ service.execute(r); } service.shutdown(); } public static void main(String[] args) { MonoThreadRunnableTaskExecutor executor = new MonoThreadRunnableTaskExecutor(); executor.add(new RunnableTask(1)); executor.add(new RunnableTask(2)); executor.add(new RunnableTask(4)); executor.add(new RunnableTask(3)); executor.start(); System.out.println("Fin des exécutions"); } }
  • 73. antislashn.org Java avancé - Programmation concurrente 2 - 73 / 94 Exécution de tâches ● Résultat de l'exécution des tâches sur un seul thread >>> START pool-1-thread-1 pour 1 s >>> FIN pool-1-thread-1 >>> START pool-1-thread-1 pour 2 s >>> FIN pool-1-thread-1 >>> START pool-1-thread-1 pour 4 s >>> FIN pool-1-thread-1 >>> START pool-1-thread-1 pour 3 s >>> FIN pool-1-thread-1
  • 74. antislashn.org Java avancé - Programmation concurrente 2 - 74 / 94 Exécution de tâches ● Exemple sur un plusieurs thread public class MultiThreadRunnableTaskExecutor { private List<Runnable> runnables = new ArrayList<>(); private ExecutorService service = Executors.newFixedThreadPool(10); public void add(Runnable runnable){ runnables.add(runnable); } public void start(){ for(Runnable r : runnables){ service.execute(r); } service.shutdown(); } public static void main(String[] args) { MultiThreadRunnableTaskExecutor executor = new MultiThreadRunnableTaskExecutor(); executor.add(new RunnableTask(1)); executor.add(new RunnableTask(2)); executor.add(new RunnableTask(4)); executor.add(new RunnableTask(3)); executor.start(); System.out.println("Fin des exécutions"); } }
  • 75. antislashn.org Java avancé - Programmation concurrente 2 - 75 / 94 Exécution de tâches ● Résultat de l'exécution des tâches sur un seul thread >>> START pool-1-thread-2 pour 2 s >>> START pool-1-thread-3 pour 4 s >>> START pool-1-thread-1 pour 1 s Fin des exécutions >>> START pool-1-thread-4 pour 3 s >>> FIN pool-1-thread-1 >>> FIN pool-1-thread-2 >>> FIN pool-1-thread-4 >>> FIN pool-1-thread-3
  • 76. antislashn.org Java avancé - Programmation concurrente 2 - 76 / 94 Tâches asynchrones ● Future ● interface représentant le traitement résultat d'un traitement asynchrone ● instances créées par ExecutorService ● Callable ● permet le retour d'une valeur après l'exécution d'une tâche – ce que ne permet pas la méthode run() de Runnable ● le callable est soumis à un exécuteur, le framework retourne un Future
  • 77. antislashn.org Java avancé - Programmation concurrente 2 - 77 / 94 Tâches asynchrones ● Exemple de Callable public class Compteur implements Callable<Long> { private final long nb; public Compteur(long nb){ this.nb = nb; } @Override public Long call() throws Exception { System.out.println(">>> "+Thread.currentThread().getName()); long sum = 0; for(long i=0; i<nb; i++) sum+=i; return sum; } }
  • 78. antislashn.org Java avancé - Programmation concurrente 2 - 78 / 94 Tâches asynchrones ● Exemple d'utilisation de Future public class CompteurFutureTest { private static final int NB_THREADS = 50; public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(NB_THREADS); List<Future<Long>> futures = new ArrayList<Future<Long>>(); for(int i=100 ; i< 120 ; i++){ Callable<Long> callable = new Compteur(i); Future<Long> future = executor.submit(callable); futures.add(future); } executor.shutdown(); long total = 0; for(Future<Long> f : futures){ try { total = f.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } System.out.println("TOTAL = "+total); } }
  • 79. antislashn.org Java avancé - Programmation concurrente 2 - 79 / 94 Tâches asynchrones ● Reportez-vous à l'atelier 7
  • 80. antislashn.org Java avancé - Programmation concurrente 2 - 80 / 94 Java 6 - ajouts ● Deux types de collections sont ajoutées ● Deque : file à double entrée – garanti les insertions et suppression efficaces aux deux extrémités – implémenté par ArrayDeque et LinkedBlockingDeque ● adaptées au pattern "Vol de tâche" – le consommateur – producteur utilise une seule file de tâches partagées par tous les consommateurs – le vol de tâche utilise un file double par consommateur, un consommateur ayant épuisé sa file peut voler la tâche à la fin d'une file double d'un autre
  • 81. antislashn.org Java avancé - Programmation concurrente 2 - 81 / 94 Java 7 : ajouts ● TransferQueue ● interface modélisant une file d'attente bloquante – le producteur attend que le consommateur prenne ce qu'il a mis dans la file ● ThreadLocalRandom ● générateur de nombres aléatoires local à un thread – évite de partager une instance de Random entre plusieurs threads ● Phaser ● barrière de synchronisation réutilisable et supportant un nombre de tâches enregistrées pouvant varier durant l'exécution
  • 82. antislashn.org Java avancé - Programmation concurrente 2 - 82 / 94 Java 7 : fork/join ● Problème de base : traiter de grandes quantités de données paquet par paquet ● chaque paquet peut être traiter de manière indépendante des autres ● chaque paquet peut fournir un résultat partiel ● les résultats partiels sont ensuite fusionnés ● La décomposition en sous tâches peut être ● statique : découpage d'un tableau en sous-tableau ● dynamique : découverte d'une arborescence d'un système de fichier – quel volume de tâches à créer ?
  • 83. antislashn.org Java avancé - Programmation concurrente 2 - 83 / 94 Java 7 : fork/join ● Différentes approches sont envisageables ● traiter les paquets les uns après les autres ● traiter les paquets en parallèle avec un point de synchronisation type CyclicBarrier ● utiliser le traitement parallèle avec ForkJoinTask
  • 84. antislashn.org Java avancé - Programmation concurrente 2 - 84 / 94 Java 7 : fork/join ● Deux classes de base ● ForkJoinTask – modélise une tâche unique qui sera envoyée à une réserve de threads – peut générer d'autres tâches du même type qui seront envoyées à la même réserve de threads ● ForkJoinPool – gère la réserve de threads – la réserve reçoit les tâches et le dispatche aux threads – réserve conçue pour qu'un grand nombre de tâches élémentaires soit traitées par un nombre restreint de threads
  • 85. antislashn.org Java avancé - Programmation concurrente 2 - 85 / 94 Java 7 : fork/join ● La machine qui exécute la tâche doit posséder plusieurs processeurs ● La tâche est récursive ● RecursiveTask : avec renvoi de résultat ● RecursiveAction : sans renvoi de résultat ● Algorithme de base d'utilisation du framework fork/join : if (my portion of the work is small enough) do the work directly else split my work into two pieces invoke the two pieces and wait for the results
  • 86. antislashn.org Java avancé - Programmation concurrente 2 - 86 / 94 Java 7 : fork/join ● La javadoc précise qu'une tâche élémentaire ● ne doit pas comporter de synchronisation afin d'éviter les blocages ● ne doivent pas partager de variables ● doivent pouvoir être exécutées rapidement
  • 87. antislashn.org Java avancé - Programmation concurrente 2 - 87 / 94 Java 7 : fork/join ● La javadoc précise qu'une tâche élémentaire ● ne doit pas comporter de synchronisation afin d'éviter les blocages ● ne doivent pas partager de variables ● doivent pouvoir être exécutées rapidement
  • 88. antislashn.org Java avancé - Programmation concurrente 2 - 88 / 94 Java 7 : fork/join ForkJoinPoolForkJoinPool Tâche longue s'occupe du découpage en sous tâches Tâche longue s'occupe du découpage en sous tâches lance la tâche sous-tâche sous-tâche sous-tâche sous-tâche sous-tâche sous-tâche sous-tâche sous-tâche fork() join()
  • 89. antislashn.org Java avancé - Programmation concurrente 2 - 89 / 94 Java 7 : fork/join ● ForkJoinTask<V> ● V : type résultat ● deux méthodes principales – join() : retourne le résultat de la tâche (V) ● bloquante tant que que la tâche n'est pas finie – fork() : lance une autre tâche dans la même réserve de pool que la tâche courante ● une même tâche ne doit pas appeler plus d'une fois sa méthode fork() ● spécialisée par RecusiveAction et RecursiveTask<V> – compute() : méthode exécutée par la tâche
  • 90. antislashn.org Java avancé - Programmation concurrente 2 - 90 / 94 Java 7 : fork/join ● Reportez-vous à l'atelier 8
  • 91. antislashn.org Java avancé - Programmation concurrente 2 - 91 / 94 Objets immuables ● La classe doit être déclarée final ● pour éviter la modification d'une instance par héritage ● Tous les champs doivent être déclarés final ● La référence this ne doit jamais être exportée ● pas de return this ;
  • 92. antislashn.org Java avancé - Programmation concurrente 2 - 92 / 94 Objets immuables ● Les propriétés référençant des objets non immuables doivent : ● être privées ● ne jamais être exportées ● représenter l'unique référence à l'objet – faire des copies défensives
  • 93. antislashn.org Java avancé - Programmation concurrente 2 - 93 / 94 Objets immuables private final Date theDate; public MaClasse(Date theDate) { this.theDate = theDate; } @Override public String toString() { return theDate.toString(); } Date d = new Date(); MaClasse c = new MaClasse(d); d.setYear(98); System.out.println(c); cette propriété peut-être exportée private final Date theDate; public MaClasse(Date theDate) { this.theDate = (Date) theDate.clone(); } copie défensive
  • 94. antislashn.org Java avancé - Programmation concurrente 2 - 94 / 94 Ressources ● Livres ● Java Threads – auteurs : Scott Oaks, Henry Wong – éditeur : O'Reilly ● Programmation concurrente en Java – auteur : Brian Goetz – éditeur : PEARSON ● web ● http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html ● http://www.oracle.com/technetwork/articles/java/fork-join-422606.html ● http://gee.cs.oswego.edu/dl/papers/fj.pdf ● http://blog.paumard.org/