Académique Documents
Professionnel Documents
Culture Documents
de casablanca
Ecole supérieure de technologie
Programmation
orientée objet
Java Avancé
Préparé par :
Larbi Hassouni
Threads En Java
HASSOUNI Larbi 2
Threads 1
Définitions
• Un programme est multitâche quand il lance
(ou peut lancer) l’exécution de plusieurs
parties de son code en même temps
• A un moment donné, il comporte plusieurs
points d’exécution liés aux différentes
parties qui s'exécutent en parallèle
HASSOUNI Larbi 3
Systèmes d’exploitation
• Tous les systèmes d'exploitation modernes
sont multitâches et ils permettent l’exécution
de programmes multitâches
• Sur une machine monoprocesseur cette
exécution en parallèle est simulée
• Si le système est préemptif, il peut à tout
moment prendre la main à un programme
pour la donner à un autre
• Sinon, un programme garde la main jusqu’à ce
qu’il la cède à un autre
HASSOUNI Larbi 4
Threads 2
Threads et processus
• Le multitâche s'appuie sur les processus ou les
threads (processus légers)
• Chaque processus a son propre espace
mémoire (espace où sont rangées les valeurs
des variables utilisées par le processus)
• Un processus peut lancer plusieurs threads qui
se partagent le même espace mémoire et
peuvent donc se partager des variables
• Un thread prend moins de ressources système
qu’un processus
HASSOUNI Larbi 5
Exemples de thread
• L’interface graphique de l’utilisateur lance un
thread pour charger une image et continue à
traiter les événements générés par les actions
de l’utilisateur
• Le serveur réseau qui attend les demandes de
connexions venant des autres machines lance
un thread pour traiter chacune des demandes
• La multiplication de 2 matrices (m, p) et (p, n)
peut être effectuée en parallèle par m n
threads
HASSOUNI Larbi 6
Threads 3
Utilité du multitâche
• Sur une machine multiprocesseurs il permet
d’améliorer les performances en répartissant les
différentes tâches sur différents processeurs
• Par exemple, le calcul du produit de 2 matrices
peut être réparti en un nombre de tâches
parallèles égal au nombre de processeurs,
• La répartition des tâches sur les processeurs est
le plus souvent faite automatiquement par le
système qui offre le multitâche
HASSOUNI Larbi 7
Threads 4
Programme comportant 3 threads
Système à multi processeurs Système à un seul processeurs
HASSOUNI Larbi 9
HASSOUNI Larbi 10
Threads 5
HASSOUNI Larbi 11
Problèmes du multitâche
HASSOUNI Larbi 12
Threads 6
Java et le multitâche
HASSOUNI Larbi 13
HASSOUNI Larbi 14
Threads 7
Interface Runnable
HASSOUNI Larbi 15
Contrôleur de thread
HASSOUNI Larbi 16
Threads 8
Classe Thread
HASSOUNI Larbi 17
Classe Thread:
Constructeurs généralement utilisés
• Thread()
• Thread(String name)
• Thread(Runnable r)
• Thread(Runnable r,String name)
HASSOUNI Larbi 18
Threads 9
Thread()Allocates a new Thread object.
Thread(ThreadGroup group, Runnable target, String name)Allocates a new Thread object so that
it has target as its run object, has the specified name as its name, and belongs to the thread group
referred to by group.
HASSOUNI Larbi 19
2 façons de créer
un contrôleur de thread
HASSOUNI Larbi 20
Threads 10
Créer un contrôleur de thread avec
une classe fille de la classe Thread
class ThreadTache extends Thread {
. . .
public void run() {
// Code qui sera exécuté par le thread
. . .
}
}
HASSOUNI Larbi 21
HASSOUNI Larbi 22
Threads 11
Quelle façon utiliser ?
HASSOUNI Larbi 24
Threads 12
public int getPriority(): retourne la priorité du thread.
HASSOUNI Larbi 25
Threads 13
Etats d'un thread
A thread can be in one of the following states:
• NEW : A thread that has not yet started is in this state
• RUNNABLE : A thread in the runnable state is executing in the Java virtual machine
but it may be waiting for other resources from the operating system such as
processor.
• BLOCKED: A thread in the blocked state is waiting for a monitor lock to enter a
synchronized block/method or reenter a synchronized block/method after calling
object.wait.
• WAITING : A thread is in the waiting state due to calling one of the following
methods:
– Object.wait with no timeout
– Thread.join with no timeout
A thread in the waiting state is waiting for another thread to perform a particular
action. For example, a thread that has called Object.wait() on an object is waiting
for another thread to call Object.notify() or Object.notifyAll() on that object. A
thread that has called Thread.join() is waiting for a specified thread to terminate
HASSOUNI Larbi 27
HASSOUNI Larbi 28
Threads 14
Cycle de vie d'un thread
Bloqué sleep()
new (BLOCKED) wait()
Thread()
notify()
HASSOUNI Larbi 29
HASSOUNI Larbi 30
Threads 15
Lancer l’exécution d'un thread
La méthode start() de la classe Thread est utilisée pour lancer
un thread nouvellement créé. Elle effectue les operations
suivantes:
Un nouveau thread démarre (avec une nouvelle
"callstack").
Le thread passe de l'état "New" à l'état "Runnable".
Lorsque le thread est sélectionéé par le scheduler, sa méthode
run() se met en exécution en parallèle avec le code qui a lance
le thread.
Attention, une erreur serait d’appeler directement la méthode
run() : la méthode run() serait exécutée par le thread qui l’a
appelée et pas par un nouveau thread(Il n’ya pas création de
thread)
HASSOUNI Larbi 31
Invocation de run() à
Lancement des threads par start:
partir de main(): run() se
Chaque thread s'exécute avec une pile séparée
partage la même pile que
main()
HASSOUNI Larbi 32
Threads 16
Relancer un thread
Attention :
• On ne peut relancer un thread qui a déjà été lancé.
• Que l’exécution de la méthode run du thread soit
terminée ou non, si on relance un thread, on obtient
une java.lang.IllegalThreadStateException
HASSOUNI Larbi 33
HASSOUNI Larbi 34
Threads 17
Différence entre planification preemptive
et time slicing
• Sous la planification preemptive, le thread qui a la
plus haute priorité s'exécute jusqu'à ce qu'il se met
en état d'attente, ou se termine, ou un thread de
plus haute priorité rentre en existance.
• Sous "time slicing", un thread s'exécute pour une
parie du temps (quantum), puis rentre dans la queue
(ou pool) des treads runnable. Le scheduler
détermine par la suie quel thread se mettra en
exécution, en se basant sur la priorité et d'autres
facteurs.
HASSOUNI Larbi 35
Threads : Exemple 1
class Ecrit extends Thread{ public class TstThr1{
public static void main (String args[]){
public Ecrit (String texte, int nb, long attente){ Ecrit e1 = new Ecrit ("Salam\n", 10, 5) ;
this.texte = texte ; Ecrit e2 = new Ecrit ("Hello\n", 12, 10) ;
this.nb = nb ; Ecrit e3 = new Ecrit ("Bonjour\n", 5, 15) ;
this.attente = attente ; e1.start() ;
e2.start() ;
} e3.start() ;
public void run (){ System.out.println(« Je suis la fonction main »);
}
try{ }
for (int i=0 ; i<nb ; i++){
System.out.print (texte) ;
sleep (attente) ;
}
}
catch (InterruptedException e) {
} // impose par sleep
}
private String texte ;
private int nb ;
private long attente ;
} HASSOUNI Larbi 36
Threads 18
Threads : Exemple 2
class Ecrit implements Runnable{ public class TstThr2{
public static void main (String args[]){
public Ecrit (String texte, int nb, long attente){ Ecrit e1 = new Ecrit ("Salam\n", 10, 5) ;
this.texte = texte ; Ecrit e2 = new Ecrit ("Hello\n", 12, 10) ;
this.nb = nb ; Ecrit e3 = new Ecrit ("Bonjour\n", 5, 15) ;
this.attente = attente ;
Thread t1 = new Thread (e1) ; t1.start() ;
} Thread t2 = new Thread (e2) ; t2.start() ;
public void run (){ Thread t3 = new Thread (e3) ; t3.start() ;
try{ System.out.println(“Je suis la fonction main”);
}
for (int i=0 ; i<nb ; i++){ }
System.out.print (texte) ;
Thread.sleep (attente) ;
// attention Thread.sleep
}
}
catch (InterruptedException e) {
} // impose par sleep
}
private String texte ;
private int nb ;
private long attente ;
}
HASSOUNI Larbi 37
Threads : Exemple 3
class Ecrit implements Runnable{ public class TstThr3{
public Ecrit (String texte, int nb, long attente){ public static void main (String args[]){
Ecrit e1 = new Ecrit ("Salam\n", 10, 5) ;
this.texte = texte ; Ecrit e2 = new Ecrit ("Hello\n", 12, 10) ;
this.nb = nb ; Ecrit e3 = new Ecrit ("Bonjour\n", 5, 15) ;
this.attente = attente ; e1.start() ;
} e2.start() ;
public void start (){ e3.start() ;
Thread t = new Thread (this) ; System.out.println(« Je suis la fonction main »);
t.start() ; }
}
}
public void run (){
try{
for (int i=0 ; i<nb ; i++){
System.out.print (texte) ;
Thread.sleep (attente) ;
}
}
catch (InterruptedException e) {
} // impose par sleep
}
private String texte ;
private int nb ;
private long attente ;
} HASSOUNI Larbi 38
Threads 19
Threads : Exemple 4
class Ecrit implements Runnable{ public class MyTstThr4{
public Ecrit (String texte, int nb, long attente){ public static void main (String args[]){
this.texte = texte ; Ecrit e1 = new Ecrit ("Salam\n", 10, 5) ;
Ecrit e2 = new Ecrit ("Hello\n", 12, 10) ;
this.nb = nb ; Ecrit e3 = new Ecrit ("Bonjour\n", 5, 15) ;
this.attente = attente ;
} Thread t1 = new Thread (e1) ; t1.start() ;
public void run (){ Thread t2 = new Thread (e2) ; t2.start() ;
try{ Thread t3 = new Thread (e3) ; t3.start() ;
for (int i=0 ; i<nb ; i++){
System.out.print (texte) ; try{
for(int i=0; i<5; i++){
Thread.sleep (attente) ; System.out.println("Fonction main");
// attention Thread.sleep Thread.sleep(100);
} }
} }
catch (InterruptedException e) { catch(InterruptedException e){
} // impose par sleep }
}
System.out.println("Je suis la fonction main");
private String texte ;
private int nb ; }
private long attente ; }
}
HASSOUNI Larbi 39
Types de Threads
• On distingue deux types de threads
– les threads utilisateur
– les démons
• La différence :
– la JVM fonctionne tant qu’il reste des threads
utilisateurs en exécution
– la JVM s’arrête s’il ne reste plus que des démons
HASSOUNI Larbi 40
Threads 20
Thread démons
(Daemon Thread)
• Un thread "Daemon" en java est un thread
fournisseur de service qui fournit des services au
thread utilisateur. Son cycle de vie dépend du cycle
de vie des threads utilisateurs.
• Lorsque tous les threads utilisateurs meurent, La JVM
termine automatiquement les threads démons.
• Il y a beucoup de threads démons qui s'exécutent
automatiquement (gc : garbage collector, finalize :
finalizer, …etc). (Pour voir tous les details, utilizer
l'utilitaire "jconsole")
HASSOUNI Larbi 41
HASSOUNI Larbi 42
Threads 21
Threads démons
• La méthode:
void setDaemon(boolean on)
de la classe Thread permet d’indiquer que le
thread sera un démon (thread utilisateur par
défaut)
• Elle doit être appelée avant le démarrage du
thread par l’appel de start()
HASSOUNI Larbi 43
HASSOUNI Larbi 44
Threads 22
Threads demons et arret brutal
class Ecrit extends Thread import java.util.Scanner;
{ public Ecrit (String texte, long attente) public class Demons
{ this.texte = texte ; { public static void main (String args[])
this.attente = attente ; { Ecrit e1 = new Ecrit ("Salam\n", 5) ;
} Ecrit e2 = new Ecrit ("Hello\n", 10) ;
Ecrit e3 = new Ecrit ("Bonjour\n", 35) ;
public void run ()
e1.setDaemon (true) ; e1.start() ;
{ try e2.setDaemon (true) ; e2.start() ;
{ while (true) // boucle infinie e3.setDaemon (true) ; e3.start() ;
{ if (interrupted()) return ; int n = new Scanner(System.in).nextInt() ;
System.out.print (texte) ; // met fin au main, donc ici aux trois autres threads démons
sleep (attente) ; }
} }
}
catch (InterruptedException e)
{ return ; // on peut omettre return ici
}
}
HASSOUNI Larbi 45
Threads 23
Threads : Exemple 5 (2/2)
HASSOUNI Larbi 47
HASSOUNI Larbi 48
Threads 24
Threads : Exemple 6 (2/2)
public static void main(String[] args) {
// Create three threads
Thread first = new Thread(new JumbleNames("Hopalong ", "Cassidy ", 200L));
Thread second = new Thread(new JumbleNames("Marilyn ", "Monroe ", 300L));
Thread third = new Thread(new JumbleNames("Slim ", "Pickens ", 500L));
// Set threads as daemon
first.setDaemon(true); second.setDaemon(true); third.setDaemon(true);
System.out.println("Press Enter when you have had enough...\n");
first.start(); // Start the first thread
second.start(); // Start the second thread
third.start(); // Start the third thread
try {
System.in.read(); // Wait until Enter key pressed
System.out.println("Enter pressed...\n");
} catch (IOException e) { // Handle IO exception
System.err.println(e); // Output the exception
}
System.out.println("Ending main()"); return;
}
private String firstName; private String secondName; private long aWhile;}
HASSOUNI Larbi 49
Dormir
• La méthode static de la classe Thread
public static void sleep(long millis)
throws InterruptedException
fait dormir le thread qui l'appelle un certain nombre
de millisecondes
• Si elle est exécutée dans du code synchronisé, le
thread ne perd pas le moniteur (au contraire de wait())
• La syntaxe est :
public static void sleep(int millis) throws InterruptedException
Exception
•InterruptedException -- Si le thread en cours est interrompu par un autre
thread, l’exception InterruptedException est lancée et son flag d’interruption est
initialisé.
HASSOUNI Larbi 50
Threads 25
Attente de la fin d’un thread
• Si dans un thread vous voulez attendre jusquà ce qu’un
autre thread meurt, vous pouvez appeler la méthode
join() pour le thread à attendre.
• La syntaxe est:
threadAattendre.join(); : Le thread en cours attend
jusqu’à ce que threadAAttendre meurt;
threadAattendre.join(long millis);
threadAattendre.join(long millis, int nanos);
• La méthode join() peut lancer l’exception
InterruptedException si le thread en cours est interrompu
par un autre thread, par consequent vous devez mettre
dans un bloc try block et capter (catch) l’exception.
HASSOUNI Larbi 51
// constructeur
public FaitQuelqueChose(String msg) {
this.msg = msg;
}
// méthode d’exécution de la thread
public void run(){
System.out.println("run: (" + msg + ") début !");
try {
Thread.sleep(5000);
}
catch (Exception e) {}
System.out.println("run: (" + msg + ") milieu...");
try {
Thread.sleep(5000);
}
catch (Exception e) {}
System.out.println("run: (" + msg + ") fin !");
}
}
HASSOUNI Larbi 52
Threads 26
public class ThreadEx {
public static void main(String[] args) throws Exception {
System.out.println("main: demarre un");
Thread t1 = new Thread(new FaitQuelqueChose("un"));
t1.start();
try {
Thread.sleep(2500);
}
catch (Exception e) {}
System.out.println("main: demarre deux");
main: demarre un
run: (un) début !
main: demarre deux
main: attente fin execution...
run: (deux) début !
run: (un) milieu...
run: (deux) milieu...
run: (un) fin !
main: t1 est fini
run: (deux) fin !
main: t2 est fini
HASSOUNI Larbi 54
Threads 27
Exécution de ThreadEx
C:\>java MineThreadEx
Passer la main
Threads 28
public class YieldingThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public YieldingThread() {
super("" + ++threadCount);
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
yield();
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++)
new YieldingThread();
}
}
HASSOUNI Larbi 57
Threads 29
Interruption de threads
class Ecrit extends Thread{ public class TstInter {
public Ecrit (String texte, long attente){ public static void main (String args[]) {
this.texte = texte ; Ecrit e1 = new Ecrit ("bonjour ", 5) ;
this.attente = attente ; Ecrit e2 = new Ecrit ("bonsoir ", 10) ;
} Ecrit e3 = new Ecrit ("\n", 35) ;
e1.start() ;
public void run (){
e2.start() ;
try{ e3.start() ;
while (true) { // boucle infinie System.out.println(«main : avant interruption e1 »);
if (interrupted()) return ; e1.interrupt() ; // interruption premier thread
System.out.print (texte) ; System.out.println ("\n** Arret premier thread **") ;
sleep (attente) ; System.out.println(«main : avant interruption e2 »);
} e2.interrupt() ; // interruption deuxième thread
e3.interrupt() ; // interruption troisième thread
}
System.out.println ("\n* Arret deux derniers threads *") ;
catch (InterruptedException e){ }
return ; // on peut omettre return ici }
}
}
HASSOUNI Larbi 59
Exécution de TstIntr
bonsoir bonjour
** Arret premier thread **
main : avant interruption e2
HASSOUNI Larbi 60
Threads 30
Partage de données
entre plusieurs threads
• Le plus simple est de créer les threads
en utilisant une classe qui implémente
Runnable et de mettre les données
partagées comme variables static
de cette classe.
HASSOUNI Larbi 61
HASSOUNI Larbi 62
Threads 31
Dans ce qui suit, nous allons discuter les capacités
basiques du langage Java pour gérer la synchronisation
entre les threads.
La librairie de concurrence fournie par les packages:
• java.util. concurrent,
• java.util.concurrent.atomic,
• java.util.concurrent.locks
Contient des classes qui implémente des facilités de
gestion des threads spécialisées,
HASSOUNI Larbi 63
Section critique
• L’utilisation de threads peut entraîner des
besoins de synchronisation pour éviter les
problèmes liés aux accès simultanés aux
variables
• En programmation, on appelle section critique
une partie du code qui ne peut être exécutée
en même temps par plusieurs threads sans
risquer de provoquer des anomalies de
fonctionnement
HASSOUNI Larbi 64
Threads 32
Exemple de problème
• Si x = 2, le code x = x + 1;
exécuté par 2 threads, peut donner en fin
d’exécution 3 ou 4 suivant l’ordre d’exécution :
1. T1 : lit la valeur de x (2)
2. T2 : lit la valeur de x (2)
3. T1 : calcul de x + 1 (3)
4. T2 : calcul de x + 1 (3)
5. T1 : range la valeur calculée dans x (3)
6. T2 : range la valeur calculée dans x (3)
• x contient 3 au lieu de 4 !
HASSOUNI Larbi 65
Synchronisation
• Il faut donc éviter l’exécution simultanée de
sections de code critiques par plusieurs threads
Threads 33
Méthodes synchronized
class MyClass {
synchronized public void method1() {
// Code for the method...
}
synchronized public void method2() {
// Code for the method...
}
public void method3() {
// Code for the method...
}
}
HASSOUNI Larbi 67
HASSOUNI Larbi 68
Threads 34
Synchronisation de threads
class Nombres {
public void calcul() {
n++ ;
carre = n*n ;
}
public void affiche () {
System.out.println (n + " a pour carre " + carre) ;
}
private int n=0, carre ;
}
Synchronisation de threads
Import java.util.Scanner;
public class Synchronisation1 {
public static void main (String args[]) {
Nombres nomb = new Nombres() ;
Thread calc = new ThrCalc (nomb) ;
Thread aff = new ThrAff (nomb) ;
System.out.println ("Suite de carres - tapez retour pour arreter") ;
calc.start() ; >java NonSynchr1
aff.start() ; Suite de carres - tapez retour pour arreter
String s = new Scanner(System.in).nextLine(); 1 a pour carre 1
calc.interrupt() ; 2 a pour carre 4
aff.interrupt() ; 3 a pour carre 9
} 5 a pour carre 25
} 6 a pour carre 49
8 a pour carre 64
9 a pour carre 100
11 a pour carre 121
13 a pour carre 169
14 a pour carre 196
16 a pour carre 256
17 a pour carre 289
18 a pour carre 324
HASSOUNI Larbi 70
Threads 35
Synchronisation de threads
class Nombres{
public /* synchronized */ void calcul(){
n++ ;
try { Thread.sleep (100) ;}
catch (InterruptedException e) {}
carre = n*n ;
}
public /* synchronized */ void affiche (){
System.out.println (n + " a pour carre " + carre) ;}
private int n=0, carre ;
}
class ThreadCalcul extends Thread{ class ThreadAffiche extends Thread {
public ThreadCalcul (Nombres nomb){ public ThreadAffiche (Nombres nomb) {
this.nomb = nomb ; this.nomb = nomb ;
} }
public void run (){ public void run () {
try { try {
while (!interrupted()){ while (!interrupted()) {
nomb.calcul () ; nomb.affiche() ;
sleep (50) ; sleep (75) ;
} }
} }
catch (InterruptedException e) {} catch (InterruptedException e) {}
} }
private Nombres nomb ; private Nombres nomb ;
} HASSOUNI Larbi } 71
Synchronisation de threads
>java Synchr1a
import java.util.Scanner; Suite de carres - tapez retour pour arreter
public class Synchronisation2 { 1 a pour carre 0
public static void main (String args[]) { 1 a pour carre 0
Scanner stdin = new Scanner(System.in); 2 a pour carre 1
2 a pour carre 1
Nombres nomb = new Nombres() ; 3 a pour carre 4
Thread calcul = new ThreadCalcul (nomb) ; 3 a pour carre 4
Thread affiche = new ThreadAffiche (nomb) ; 4 a pour carre 9
4 a pour carre 9
System.out.println ("Suite de carres – 5 a pour carre 16
tapez retour pour arreter") ; 5 a pour carre 16
calcul.start() ; 6 a pour carre 25
affiche.start() ; 6 a pour carre 25
7 a pour carre 36
String s = stdin.nextLine(); 7 a pour carre 36
calcul.interrupt() ; 8 a pour carre 49
affiche.interrupt() ; 8 a pour carre 49
9 a pour carre 64
} 9 a pour carre 64
} 10 a pour carre 81
10 a pour carre 81
11 a pour carre 100
11 a pour carre 100
12 a pour carre 121
12 a pour carre 121
HASSOUNI Larbi 72
Threads 36
Synchronisation de threads
class Nombres {
public synchronized void calcul() {
n++ ;
carre = n*n ;
}
public synchronized void affiche () {
System.out.println (n + " a pour carre " + carre) ;
}
private int n=0, carre ;
}
Synchronisation de threads
import java.util.Scanner;
public class Synchr1 {
public static void main (String args[]) {
Scanner stdin = new Scanner(System.in); C:\>java Synchr1
Nombres nomb = new Nombres() ; Suite de carres - tapez retour pour arreter
1 a pour carre 1
Thread calc = new ThrCalc (nomb) ; 2 a pour carre 4
Thread aff = new ThrAff (nomb) ; 4 a pour carre 16
5 a pour carre 25
System.out.println ("Suite de carres – 6 a pour carre 36
tapez retour pour arreter") ; 8 a pour carre 64
9 a pour carre 81
calc.start() ; 11 a pour carre 121
aff.start() ; 12 a pour carre 144
14 a pour carre 196
String s = stdin.nextLine(); 15 a pour carre 225
calc.interrupt() ; 17 a pour carre 289
18 a pour carre 324
aff.interrupt() ; 20 a pour carre 400
} 21 a pour carre 441
23 a pour carre 529
} 24 a pour carre 576
26 a pour carre 676
27 a pour carre 729
HASSOUNI Larbi 74
Threads 37
Moniteur ou verrou d’un objet
HASSOUNI Larbi 75
Threads 38
Synchronisation
• Aucun autre thread ne peut exécuter du code
synchronisé sur le même objet o tant que t exécute
le code synchronisé
• Si un autre thread veut exécuter du code synchronisé
sur o, il est mis en attente
• Lorsque t quitte le code synchronisé ou se met en
attente par o.wait(), un des threads en attente
peut redémarrer
• Les autres threads en attente auront la main à tour
de rôle (si tout se passe bien…)
HASSOUNI Larbi 77
Exemple
public class Compte {
private double solde;
HASSOUNI Larbi 78
Threads 39
Exemple (suite)
• On lance 3 threads du type suivant :
Thread t1 = new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
compte.deposer(1000);
}
}
};
• A la fin de l’exécution, on n’obtient pas nécessairement
300.000
• Il faut rendre deposer (et getSolde) synchronisée :
public synchronized
void deposer(double somme)
HASSOUNI Larbi 79
Synchronisation et performances
• L’exécution de code synchronisé nuit aux
performances
• Surtout s’il provoque des blocages entre
threads ; si pas de blocage, peu de perte de
performance
• Mais, de plus, du code synchronisé peut
empêcher des optimisations (inlining) au
moment de la compilation
HASSOUNI Larbi 80
Threads 40
Méthodes statiques
HASSOUNI Larbi 81
HASSOUNI Larbi 82
Threads 41
wait et notify
HASSOUNI Larbi 83
Exécution conditionnelle
• Lorsqu’un programme est multi-tâche, la
situation suivante peut se rencontrer :
– Un thread t1 ne peut continuer son exécution
que si une condition est remplie
– Le fait que la condition soit remplie ou non
dépend d’un autre thread t2
• Par exemple, t1 veut utiliser le résultat d’un
calcul effectué par t2
HASSOUNI Larbi 84
Threads 42
Exécution conditionnelle (2)
• Une solution coûteuse serait que t1 teste la
condition à intervalles réguliers
• Les méthodes wait() et notify() de la
classe Object permettent de programmer
plus efficacement ce genre de situation
HASSOUNI Larbi 85
Threads 43
Exemple d’utilisation de wait et notifyAll
HASSOUNI Larbi 87
HASSOUNI Larbi 88
Threads 44
class ThreadPuise extends Thread{
HASSOUNI Larbi 89
import java.util.Scanner;
public class Synchro3{
public static void main (String args[]){
Reserve r = new Reserve () ;
ThreadAjout ta1 = new ThreadAjout (r, 100, 15) ;
ThreadAjout ta2 = new ThreadAjout (r, 50, 20) ;
ThreadPuise tp = new ThreadPuise (r, 300, 10) ;
System.out.println ("Suivi de stock --- Taper entree pour arreter ") ;
ta1.start () ; ta2.start () ; tp.start () ;
String s = new Scanner(System.in).nextLine();
ta1.interrupt () ; ta2.interrupt () ; tp.interrupt () ;
}
}
HASSOUNI Larbi 90
Threads 45
Besoin de synchronisation
• Le mécanisme d’attente-notification lié à un
objet met en jeu l’état interne de l’objet ;
pour éviter des accès concurrent à cet état
interne, une synchronisation est nécessaire
• Les appels:
-objet.wait()
-objet.notify()
-objet.notifyAll())
ne peuvent donc être effectués que dans du
code synchronisé sur objet
HASSOUNI Larbi 91
Méthode wait()
• public final void wait()
throws InterruptedException
• objet.wait()
– nécessite que le thread en cours possède le
moniteur de objet
– bloque le thread qui l’appelle, jusqu’à ce qu’un
autre thread appelle la méthode
objet.notify() ou objet.notifyAll()
– libère le moniteur de l’objet (l’opération « blocage
du thread – libération du moniteur » est atomique)
HASSOUNI Larbi 92
Threads 46
Méthode notifyAll()
HASSOUNI Larbi 93
Méthode notifyAll()
• Un seul des threads débloqués va récupérer le
moniteur ; on ne peut prévoir lequel
• Les autres devront attendre qu’il relâche le
moniteur pour être débloqués à tour de rôle,
mais ils ne sont plus bloqués par un wait
• En fait, souvent ils se bloqueront à nouveau
eux-mêmes (s’ils sont dans une boucle while
avec wait)
HASSOUNI Larbi 94
Threads 47
Méthode notify()
• objet.notify()
– idem notifyAll() mais
– ne débloque qu’un seul thread
• On ne peut prévoir quel sera le thread
débloqué et, le plus souvent, il vaut donc mieux
utiliser notifyAll()
HASSOUNI Larbi 95
HASSOUNI Larbi 96
Threads 48
notify perdus
HASSOUNI Larbi 97
HASSOUNI Larbi 98
Threads 49
Exemple avec wait-notify
public class Depot {
private int nbJetons = 0;
public synchronized void donneJeton() {
try {
while (nbJetons == 0) {
wait();
}
nbJetons--;
}
catch (InterruptedException e) {}
}
HASSOUNI Larbi 99
Threads 50
Variante de wait
Moniteurs réentrants
Threads 51
Affectations atomiques
• Il est inutile de synchroniser une partie de
code qui ne fait qu'affecter (ou lire) une valeur
à une variable de type primitif de longueur 32
bits ou moins (int, short, …)
• En effet, la spécification du langage Java
spécifie qu'une telle affectation ne peut être
interrompue pour donner la main à un autre
thread
• Mais, cette spécification n'assure rien pour les
affectations de double et de long !
HASSOUNI Larbi 103
Threads 52
Importantes méthodes de la classe ThreadGroup
• Il ya plusieurs méthodes dans la classe ThreadGroup. La liste ci-dessous
fournit les noms des plus importantes.
Méthode Description
Returns an estimate of the number of active
int activeCount() threads in this thread group and its
subgroups.
void destroy() Destroys this thread group and all of its
subgroups.
String getName() returns the name of this group.
ThreadGroup getParent() returns the parent of this group.
void interrupt() interrupts all threads of this group.
void list() prints information of this group to standard
console.
Called by the Java Virtual Machine when a
Void thread in this thread group stops because of
uncaughtException(Thread t, an uncaught exception, and the thread does
Throwable e) not have a specific
Thread.UncaughtExceptionHandler installed.
Threads 53
Exemple de programme utilisant ThreadGroup
public class ThreadGroupDemo implements Runnable{
@Override
public void run(){
while(!Thread.currentThread().interrupted()){
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args){
ThreadGroupDemo runnable = new ThreadGroupDemo();
ThreadGroup tg1 = new ThreadGroup("Parent ThreadGroup");
Thread t1 = new Thread(tg1, runnable, "one");
t1.start();
Thread t2 = new Thread(tg1, runnable, "two");
t2.start();
Thread t3 = new Thread(tg1, runnable, "three");
t3.start();
System.out.println("Thread Group name : " + tg1.getName());
tg1.list();
tg1.interrupt();
}
}
HASSOUNI Larbi 107
Shutdown Hook
• The shutdown hook can be used to perform cleanup resource
or save the state when JVM shuts down normally or abruptly.
Performing clean resource means closing log file, sending
some alerts or something else. So if you want to execute some
code before JVM shuts down, use shutdown hook.
• When does the JVM shut down?
The JVM shuts down when:
user presses ctrl+c on the command prompt
System.exit(int) method is invoked
user logoff
user shutdown etc.
Threads 54
The addShutdownHook(Runnable r) method
The addShutdownHook() method of Runtime class is used to register the thread with the
Virtual Machine.
Syntax: public void addShutdownHook(Runnable r){}
The object of Runtime class can be obtained by calling the static factory method
getRuntime(). For example:
Runtime r = Runtime.getRuntime();
Factory method
The method that returns the instance of a class is known as
factory method.
Threads 55
Same example of Shutdown Hook by annonymous class:
Priorités
Threads 56
Principe de base
• Si plusieurs threads de même priorité sont en
exécution, on ne peut pas prévoir quel thread va
prendre la main
• S’ils sont en attente d’exécution, un thread de
plus grande priorité prendra toujours la main
avant un autre thread de priorité plus basse
• Cependant, il peut arriver exceptionnellement
qu’un thread continue son exécution alors que
des threads de priorité supérieure sont en attente
d’exécution
Niveaux de priorité
• Un nouveau thread a la même priorité que le
thread qui l’a créé
• En général, tous les threads ont la même priorité
(NORM_PRIORITY =5)
• Il faut faire appel à la méthode setPriority si
on veut modifier cette priorité par défaut
• Le paramètre de setPriority doit être
compris entre MIN_PRIORITY(1) et
MAX_PRIORITY(10)
Threads 57
Threads et exceptions
Threads et exceptions
Threads 58
Depuis Java 5, Il existe l'interface
UncaughtExceptionHandler qui contient une seule
méthode, uncaughtException(Thread t, Throwable e),
et qui permet de récupérer les exceptions non gérées
avant que le thread ne meure définitivement.
Nested Classes
Modifier and Class and Description
Type
static class Thread.State A thread state.
static interface Thread.UncaughtExceptionHandler Interface for
handlers invoked when a Thread abruptly
terminates due to an uncaught exception.
@FunctionalInterface
public static interface Thread.UncaughtExceptionHandler{
void uncaughtException(Thread t, Throwable e);
}
Threads 59
setUncaughtExceptionHandler
public void setUncaughtExceptionHandler(Thread.
UncaughtExceptionHandler eh)
Set the handler invoked when this thread abruptly terminates due to
an uncaught exception.
A thread can take full control of how it responds to uncaught
exceptions by having its uncaught exception handler explicitly set. If
no such handler is set then the thread's ThreadGroup object acts as
its handler.
Parameters:
eh : the object to use as this thread's uncaught exception handler.
If null then this thread has no explicit handler.
getUncaughtExceptionHandler
public Thread.UncaughtExceptionHandler getUnca
ughtExceptionHandler()
Returns the handler invoked when this thread abruptly
terminates due to an uncaught exception. If this thread has
not had an uncaught exception handler explicitly set then
this thread's ThreadGroup object is returned, unless this
thread has terminated, in which case null is returned.
Returns:
the uncaught exception handler for this thread
Threads 60
setDefaultUncaughtExceptionHandler
public
static void setDefaultUncaughtExceptionHandler(Thread.U
ncaughtExceptionHandler eh)
Set the default handler invoked when a thread abruptly terminates due to an
uncaught exception, and no other handler has been defined for that thread.
Uncaught exception handling is controlled first by the thread, then by the
thread's ThreadGroup object and finally by the default uncaught exception handler.
If the thread does not have an explicit uncaught exception handler set, and the
thread's thread group (including parent thread groups) does not specialize its
uncaughtException method, then the default handler's uncaughtException method
will be invoked.
Parameters:
eh - the object to use as the default uncaught exception handler. If null then there is
no default handler.
getDefaultUncaughtExceptionHandler
public
static Thread.UncaughtExceptionHandler getD
efaultUncaughtExceptionHandler()
Returns the default handler invoked when a thread abruptly
terminates due to an uncaught exception. If the returned
value is null, there is no default.
Returns:
the default uncaught exception handler for all threads
Threads 61
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.Thread.UncaughtExceptionHandler;
Threads 62
import java.util.Random;
public class ThreadException extends Thread{
public ThreadException(String name){
setName(name);
setDefaultUncaughtExceptionHandler(new
MyUncaughtExceptionHandler());
}
public void run(){
Random rand = new Random();
while(true){
int cas = rand.nextInt(5);
switch(cas){
case 0 : int i = 10 / 0; break;
case 1 : Object str = "toto"; double d = (double) str;
break;
default :
System.out.println(getName() + ": aucune erreur...");
break;
} } }}
Threads 63
Utilisation de EXECUTORS
Bien à vous
Threads 64
Les flux d’entrée/sortie
En Java
L.HASSOUNI 2
Flux d'E/S 1
Flux (Streams)
L.HASSOUNI 3
keyboard
standard
input stream
CPU
standard
output MEM
monitor stream
terminal file
console input
stream
LOAD HDD
READ
Streams file
files output
stream
L.HASSOUNI SAVE
4
WRITE
Flux d'E/S 2
Flux d’entrée et de sortie standards
• Un flux d’entrée peut provenir du clavier ou d’un
fichier
– System.in est le flux d’entrée connecté au clavier
Scanner kb = new Scanner(System.in);
L.HASSOUNI 5
Program
Input stream
Input object
created from an 01011…1001 File
input class
Output object
created from an 11001…1011
File
output class
Output stream
PrintWriter output = new PrintWriter("temp.txt");
PrintWriter output =101");
output.println("Java new PrintWriter("temp.txt");
output.println("Java 101");
output.close();
L.HASSOUNI 6
output.close();
Flux d'E/S 3
Fichiers textes et fichiers binaires
• Les fichiers destinés à être lu par un humain et qui
peuvent être lus et écrits par un éditeur de texte
sont appelés fichiers textes
– Les fichiers textes sont ausi appelés fichier ASCII
puisque les données qu’ils contiennent utilisent le
schema d’encodage ASCII
– L’avantage des fichiers texte est qu’ils sont souvent
identiques sur tous les ordinateurs, par consequent on
peut les déplacer d’un ordinateur à l’autre
L.HASSOUNI 7
– Les fichiers binaires sont destinés à être lus sur le même type
d’ordinateur, et avec le même langage de programmation
que celui sur lequel le fichier a été crée la première fois
L.HASSOUNI 8
Flux d'E/S 4
Fichiers textes et fichiers binaires
• Un programme source java est un fichier texte que vous pouvez
lire en utilisant un éditeur de texte.
• Par contre un fichier .class qui mémorise le bytecode de la
classe est un fichier binaire et est lu par la JVM.
L.HASSOUNI 9
E/S binaire
Une E/S texte nécessite un encodage et un décodage.
Lorsqu’on écrit un caractère dans un fichier texte, la JVM
convertit le code Unicode en utilisant un encodage
spécifique au fichier qui depend de l’os utilisé et on
effectue l’operation inverse durant la lecture d’un
caractère.
Une E/S binaire ne nécessite pas cette conversion.
Lorsque vous écrivez un octet dans un fichier, l’octet
original est écrit tel quel dans le fichier et lorsque vous
lisez un octet à partir d’un fichier, l’octet exact tel quel
stocké dans le fichier est retourné.
10
Flux d'E/S 5
Text I/O program
L.HASSOUNI 11
ObjectOutputStream PrintStream
Flux d'E/S 6
Classe <<interface>>
AutoCloseable
InputStream
Object
<<Interface>>
Closeable
<<abstract>>
InputStream
L.HASSOUNI 13
API InputStream(1)
int available()
Returns an estimate of the number of bytes that can be read (or
skipped over) from this input stream without blocking by the next
invocation of a method for this input stream.
void close()
Closes this input stream and releases any system resources
associated with the stream
void mark(int readlimit)
Marks the current position in this input stream.
boolean markSupported()
Tests if this input stream supports the mark and reset methods.
L.HASSOUNI 14
Flux d'E/S 7
API InputStream(2)
public abstract int read() throws IOException
Reads the next byte of data from the input stream. The value byte is returned as
an int in the range 0 to 255. If no byte is available because the end of the stream has
been reached, the value -1 is returned. This method blocks until input data is available,
the end of the stream is detected, or an exception is thrown. A subclass must provide an
implementation of this method.
Int read(byte[] b)
Reads some number of bytes from the input stream and stores
them into the buffer array b.
Void reset()
Repositions this stream to the position at the time
the mark method was last called on this input stream.
long skip(long n)
Skips over and discards n bytes of data from this input stream
L.HASSOUNI 15
Classe <<interface>>
AutoCloseable
OutputStream
Object
<<Interface>> <<Interface>>
Closeable Flushable
<<abstract>>
OutputStream
L.HASSOUNI 16
Flux d'E/S 8
API OutputStream
public void close()
Closes this output stream and releases any system resources associated with this stream.
Flushes this output stream and forces any buffered output bytes to be written out.
Writes len bytes from the specified byte array starting at offset off to this output stream.
L.HASSOUNI 17
FileInputStream/FileOutputStream
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
Flux d'E/S 9
FileInputStream
Pour construire un objet FileInputStream, utilisez les
constructeurs suivants:
public FileInputStream(String filename)
public FileInputStream(File file)
L.HASSOUNI 19
FileOutputStream
Pour construire un objet FileOutputStream, utilisez les constructeurs
suivants:
Flux d'E/S 10
package mypkg;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class My03FileInputStream {
public static void main(String[] args) {
String srcFile = "src\\pkg01\\My02ScannerPrintWriter.java";
L.HASSOUNI 21
package pkg01;
import java.io.*;
public class My031FileOutputStream {
public static void main(String[] args) throws IOException
{
// Create an output stream to the file
FileOutputStream output = new FileOutputStream("temp.dat");
// Output values to the file
for (int i = 1; i <= 10; i++) output.write(i);
// Close the output stream
output.close();
Flux d'E/S 11
FilterInputStream/FilterOutputStream
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
Filter streams
L.HASSOUNI 23
L.HASSOUNI 24
Flux d'E/S 12
DataInputStream/DataOutputStream
DataInputStream lit les octets à partir du flux et les
convertit vers le type primitif approprié ou en String.
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
DataInputStream
extends FilterInputStream and
implements the DataInput interface.
L.HASSOUNI 26
26
Flux d'E/S 13
DataInputStream
DataInputStream extends FilterInputStream
and implements the DataInput interface.
InputStream java.io.DataInput
L.HASSOUNI 27
DataOutputStream
extends FilterOutputStream and
implements the DataOutput interface.
L.HASSOUNI 28
28
Flux d'E/S 14
DataOutputStream
DataOutputStream extends FilterOutputStream and implements the
DataOutput interface.
OutputStream java.io.DataOutput
L.HASSOUNI 30
Flux d'E/S 15
pourquoi UTF-8? Qu’est ce que UTF-8?
UTF-8 est une méthode de codification des caractères qui permet aux
systèmes d’utiliser à la fois le code ASCII et l’UNICODE de manière
efficace.
Les valeurs Unicode qui sont inférieures à 0x7FF sont stockées sur
deux octets. Les autres valeurs Unicode sont codées sur 3 octets.
L.HASSOUNI 32
Flux d'E/S 16
Utilisation de DataInputStream/DataOutputStream
Les classes Data streams sont utilisées comme des enveloppes pour les
flux d’E/S pour filtrer les données dans le flux original.
Ils sont créés en utilisant les constructeurs ci-dessous:
public DataInputStream(InputStream instream)
public DataOutputStream(OutputStream outstream)
L’ordre et le format
L.HASSOUNI 34
Flux d'E/S 17
import java.io.*;
public class My04DataInputOutputStream {
public static void main(String[] args) throws IOException {
// Create an output stream for file temp.dat
DataOutputStream output =
new DataOutputStream(new FileOutputStream("grade.dat"));
// Write student test scores to the file
output.writeUTF("Moha");output.writeDouble(15.50);
output.writeUTF("Manolo");output.writeDouble(17.50);
output.writeUTF("Toto");output.writeDouble(12.00);
// Close output stream
output.close();
L.HASSOUNI 36
Flux d'E/S 18
package pkg01;
import java.io.*;
public class My05DetectEndOfFile {
public static void main(String[] args) {
try {
DataOutputStream output =
new DataOutputStream(new FileOutputStream("test.dat"));
output.writeDouble(4.5);
output.writeDouble(43.25);
output.writeDouble(3.2);
output.close();
DataInputStream input =
new DataInputStream(new FileInputStream("test.dat"));
while (true) {
System.out.println(input.readDouble());
}
}
catch (EOFException ex) { System.out.println("All data were
read"); }
catch (IOException ex) { ex.printStackTrace(); }
}
}
L.HASSOUNI 37
import java.io.*;
public class My06DetectEndOfFile2 {
public static void main(String[] args) {
try {
DataOutputStream output =new DataOutputStream(new
FileOutputStream("test.dat"));
output.writeDouble(4.5);
output.writeDouble(43.25);
output.writeDouble(3.2);
output.close();
DataInputStream input =new DataInputStream(new
FileInputStream("test.dat"));
while (input.available()>0) {
System.out.println(input.readDouble());
}
}
catch (EOFException ex) { System.out.println("All data were
read"); }
catch (IOException ex){ex.printStackTrace();}
} }
L.HASSOUNI 38
Flux d'E/S 19
Copier un Fichier
Ce cas d’étude développe un programme qui copie un fichier.
L’utilisateur doit fournir le nom du fichier source et celui du fichier
destination comme argument dans la ligne de commande
39
L.HASSOUNI
L.HASSOUNI 40
Flux d'E/S 20
//Create an input stream
BufferedInputStream input =
new BufferedInputStream(new FileInputStream(sourceFile));
// Close streams
input.close(); output.close();
L.HASSOUNI 41
BufferedInputStream/BufferedOutputStream
réduisent le nombre d’accès au disque
Using buffers to speed up I/O
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
Flux d'E/S 21
Construction des objets
BufferedInputStream/BufferedOutputStream
// Create a BufferedInputStream
public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in, int bufferSize)
// Create a BufferedOutputStream
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStreamr out, int bufferSize)
L.HASSOUNI 43
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream
ObjectOutputStream PrintStream
L.HASSOUNI 44
Flux d'E/S 22
Les classes ObjectInputStream/ObjectOutputStream peuvent être
utilisées pour lire/écrire des objets sérialisables.
L.HASSOUNI 45
ObjectInputStream
extends InputStream and
implements two interfaces
the ObjectInput interface and
the ObjectStreamConstants interface.
L.HASSOUNI 46
46
Flux d'E/S 23
ObjectInputStream
ObjectInputStream extends InputStream and
implements ObjectInput and ObjectStreamConstants.
java.io.InputStream ObjectStreamConstants
java.io.DataInput
java.io.ObjectInputStream java.io.ObjectInput
ObjectOutputStream
extends OutputStream and
implements two interfaces
the ObjectOutput interface and
the ObjectStreamConstants interface.
L.HASSOUNI 48
48
Flux d'E/S 24
ObjectOutputStream
ObjectOutputStream extends OutputStream and
implements ObjectOutput and ObjectStreamConstants.
java.io.OutputStream ObjectStreamConstants
java.io.DataOutput
java.io.ObjectOutputStream java.io.ObjectOutput
// Create an ObjectInputStream
public ObjectInputStream(InputStream in)
// Create an ObjectOutputStream
public ObjectOutputStream(OutputStream out)
L.HASSOUNI 50
Flux d'E/S 25
Exemple de programmes
package pkg01;
import java.io.Serializable;
class Personne implements Serializable {
private String nom ;
private String genre;
private double taille;
public Personne(String nom, String genre, double taille){
this.nom = nom;
this.genre = genre;
this.taille = taille; }
@Override
public String toString() {
return "Nom: " + this.nom + ", Gendre: " + this.genre + ", Taille: " + this.taille;
}}L.HASSOUNI 51
L.HASSOUNI 52
Flux d'E/S 26
Lecture d'objet à partir un fichier
package objectoutputstream;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class M09ObjectRead {
public static void main(String[] args) {
File fileObject = new File("person.ser");
try (ObjectInputStream ois = new ObjectInputStream(new
FileInputStream(fileObject))) {
Personne p1 = (Personne) ois.readObject();
Personne p2 = (Personne) ois.readObject();
Personne p3 = (Personne) ois.readObject();
System.out.println(p1);
System.out.println(p2);
System.out.println(p3);
} catch (Exception e) {e.printStackTrace(); }
}}
L.HASSOUNI 53
Flux d'E/S 27
Lecture types primitifs avec ObjectOutputStream
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
L.HASSOUNI 55
L.HASSOUNI 56
Flux d'E/S 28
L’interface Serializable
• Pas n’importe quel objet peut être écrit dans un flux de sortie.
• Un objet qui peut être écrit dans un flux de sortie est dit
sérialisable.
• Pour qu’un objet soit sérialisable, il faut qu’il soit instance de
l’interface java.io.Serializable autrement dit sa classe doit
implementer Serializable.
• L’interface Serializable est une interface “marker” ou “tag”. Il
ne contient aucune méthode, par conséquent vous n’avez pas à
ajouter du code supplémentaire à votre classe qui l’implémente
L.HASSOUNI 57
L.HASSOUNI 58
Flux d'E/S 29
• Pour percevoir l’intérêt de cette automatisation de stockage
des objets, imaginez que vous devez stocker un ArrayList
d’objets.
• Pour accomplir cette tâche, vous devez stocker chaque
élément de la liste. Et chaque élément est un objet qui peut
contenir des attributs objets.
• Java vous évite de faire cette operation, qui peut être
compliquée et ennuyeuse, en fournissant un mécanisme
prédéfinie pour automatiser l’écriture des objets dans un
flux. Ce processu est désigné par “sérailisation d’objets”
qui est implémenté dans ObjectOutputStream.
• Le processus de lecture des objets est désigné par
“deserialization d’objet”, et est implémenté dans
ObjectInputStream.
L.HASSOUNI 59
L.HASSOUNI 60
Flux d'E/S 30
• La sérialisation d’un objet consiste à stocker:
– le code de sa classe qui consiste en son nom et sa
“signature”;
– Les valeurs de ses variables d’instances de types primitfs.
– Des informations sur ses attributs de type objets.
• Les valeurs de ses variables static ne sont pas
stockées.
• Remarque1:
– Si un objet instance Serialisable contient un attribut non
sérialisable, l’objet est non sérialisable.
– Pour qu’il soit sériasable, il faut déclarer l’attribut non
sérialsable avec le mot clé « transient » pour signaler à
la JVM d’ignorer la valeur de tel attribut lors de la
sérialisation de l’objet,
L.HASSOUNI 61
L.HASSOUNI 62
Flux d'E/S 31
• Remarque2:
L.HASSOUNI 63
Serialisation de tableaux
• Un tableau est sérialisable si tous ses éléments
sont sérialisables.
• Un tableau entier peut être sérialsé dans un fichier
en utilisant la méthode writeObject de l’objet
ObjectOutputStraem.
• Un tableau entier peut être déserialisé en utilisant
la méthode readObject de l’objet
ObjectInputStream.
• L’exemple suivant stocke dans un fichier un
tableau de 5 entier et un tableau de 3 strings puis
les lits pour les afficher sur l’écran.
L.HASSOUNI 64
Flux d'E/S 32
package objectoutputstream;
import java.io.*;
public class My12ObjectStreamForArray {
public static void main(String[] args)
throws ClassNotFoundException, IOException {
int[] numbers = {1, 2, 3, 4, 5};
String[] strings = {"Maha", "Toto", "Manolo"};
L.HASSOUNI 65
L.HASSOUNI 66
Flux d'E/S 33
Exécuter les deux programmes qui suivent
package objectoutputstream;
import java.io.Serializable; import java.io.File;
import java.io.FileOutputStream; import java.io.IOException;
import java.io.ObjectOutputStream;
public class My13ObjectWrite {
public static void main(String[] args) {
Personne p1 = new Personne("Moha", "Male", 1.7);
Personne p2 = new Personne("Toto", "Male", 1.7);
Personne p3 = new Personne("Manolo", "Femelle", 1.4);
Personne p4 = new Personne("Moha", "Male", 1.7);
Personne p5 = p1; Personne p6 = p1;
File fileObject = new File("person.ser");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
fileObject))) {
oos.writeObject(p1); oos.writeObject(p2); oos.writeObject(p3);
oos.writeObject(p4); oos.writeObject(p5); oos.writeObject(p6);
System.out.println("p1 : " + p1); System.out.println("p2 : " + p2);
System.out.println("p3 : " + p3); System.out.println("p4 : " + p4);
System.out.println("p5 : " + p5); System.out.println("p6 : " + p6);
} catch (IOException e) { e.printStackTrace(); } }
L.HASSOUNI 67
L.HASSOUNI 68
Flux d'E/S 34
Fichiers à accès directe
• Tous les flux que nous avons utiliés jusqu’à maintenant
sont connus comme des flux à “Lecture unique” (read-
only) ou à “Ecriture unique” (write-only).
• Le fichier externe qui correspond à ces flux est un
fichier séquentiel qui ne peut pas être mis à jour sans
créer un autre fichier.
• Il est souvent necessaire de modifier un fichier ou
d’insérer de nouveaux enregistrements dans un fichier.
• Java fournit la classe RandomAccessFile qui permet à
un fichier d’être lu ou écrit à une position aléatoire.
• Un fichier qui est ouvert en utilisant la classe
RandomAccessFile est reconnu sous le nom de fichier
à accès direct (random-access file).
L.HASSOUNI 69
RandomAccessFile
extends n/a and
implements two interfaces
the DataInput interface and
the DataOutput interface.
L.HASSOUNI 70
70
Flux d'E/S 35
API RandomAccesFile(1)
Constructors
public RandomAccessFile(File file, String mode) throws
FileNotFoundException
Creates a random access file stream to read from, and
optionally to write to, the file specified by the File argument.
public RandomAccessFile(String name, String mode) throws
FileNotFoundException
Creates a random access file stream to read from, and
optionally to write to, a file with the specified name.
L.HASSOUNI 71
RandomAccessFile raf =
new RandomAccessFile("test.dat", "rw"); //autorise la
lecture et l’écriture
RandomAccessFile raf =
new RandomAccessFile("test.dat", "r"); //autorise la
lecture uniquement
L.HASSOUNI 72
Flux d'E/S 36
File Pointer
• Un fichier à accès direct consiste en une séquence d’octets.
• Il existe un marqueur special désigné par “pointeur de fichier” et
qui est positionné sur un de ces octets.
• Une operation de lecture ou écriture concerne l’octet sur lequel est
positionné le pointeur.
• Lorsqu’un fichier est ouvert, le pointeur du fichier est positionné
au debut sur le premier octet du fichier.
• Lorsque vous effectuez une operation de lecture ou d’écriture, le
pointeur avance pour pointer l’octet suivant.
• Par exemple, si vous lisez une valeur de type int en utilisant
readInt(), la JVM lit 4 octets à partir du fichier et le pointeur
avance de 4 positions pour pointer vers l’entier suivant.
L.HASSOUNI 73
file pointer
file byte byte … byte byte byte byte byte … byte byte byte byte byte (A) Before readInt()
file pointer
file byte byte … byte byte byte byte byte … byte byte byte byte byte (B) Before readInt()
L.HASSOUNI 74
Flux d'E/S 37
API RandomAccesFile(2)
Methods
Public void close()
Closes this random access file stream and releases any system resources
associated with the stream.
Public FileChannel getChannel()
Returns the unique FileChannel object associated with this file.
L.HASSOUNI 75
L.HASSOUNI 76
Flux d'E/S 38
Public void readFully(byte[] b)
Reads b.length bytes from this file into the byte array, starting at the current
file pointer.
Public void readFully(byte[] b, int off, int len)
Reads exactly len bytes from this file into the byte array, starting at the
current file pointer.
Public int readInt() : Reads a signed 32-bit integer from this file.
Public String readLine() : Reads the next line of text from this file.
Public long readLong() : Reads a signed 64-bit integer from this file.
Public short readShort() : Reads a signed 16-bit number from this file.
Public int readUnsignedByte() : Reads an unsigned eight-bit number from
this file.
Public int readUnsignedShort() : Reads an unsigned 16-bit number from
this file.
Public String readUTF() : Reads in a string from this file.
L.HASSOUNI 77
Flux d'E/S 39
void writeChar(int v)
Writes a char to the file as a two-byte value, high byte first.
void writeChars(String s)
Writes a string to the file as a sequence of characters.
void writeDouble(double v)
Converts the double argument to a long using thedoubleToLongBits method
in class Double, and then writes thatlong value to the file as an eight-byte
quantity, high byte first.
void writeFloat(float v)
Converts the float argument to an int using the floatToIntBitsmethod in
class Float, and then writes that int value to the file as a four-byte quantity,
high byte first.
void writeInt(int v) : Writes an int to the file as four bytes, high byte first.
void writeLong(long v) : Writes a long to the file as eight bytes, high byte first.
void writeShort(int v) : Writes a short to the file as two bytes, high byte first.
void writeUTF(String str)
Writes a string to the file using modified UTF-8 encoding in a machine-
independent manner.
L.HASSOUNI 79
Source: TestRandomAccessFile.java
import java.io.*;
public class TestRandomAccessFile {
public static void main(String[] args) throws IOException {
// Create a random access file
RandomAccessFile inout = new RandomAccessFile("inout.dat", "rw");
Flux d'E/S 40
Source: TestRandomAccessFile.java
// Retrieve the tenth number
inout.seek(9 * 4); // Move the file pointer to the tenth number
System.out.println("The tenth number is " + inout.readInt());
inout.close();
}
} L.HASSOUNI 81
package myrandomfile;
public class Etudiant {
private int num;
private String nom;
private String prenom;
private char genre;
private double note;
public int getNum() {return num;}
public void setNum(int num) {this.num = num;}
public String getNom() {return nom;}
public void setNom(String nom) {this.nom = nom;}
public String getPrenom() {return prenom;}
public void setPrenom(String prenom) {this.prenom = prenom;}
public char getGenre() {return genre;}
public void setGenre(char genre) {this.genre = genre;}
public double getNote() {return note;}
public void setNote(double note) {this.note = note;}
public String toString(){
return "[" + num + " , " + nom + " , " + prenom + " , " + " , " + note
+"]"; }}
L.HASSOUNI 82
Flux d'E/S 41
package myrandomfile;
import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Scanner;
L.HASSOUNI 83
L.HASSOUNI 84
Flux d'E/S 42
public static void consultationSequentielle(RandomAccessFile raf){
try{
Etudiant e = new Etudiant();
raf.seek(0);
while(true){
e.setNum(raf.readInt());
e.setNom(raf.readUTF());
e.setPrenom(raf.readUTF());
e.setNote(raf.readDouble());
System.out.println(e);}
}catch(EOFException eof){
System.out.println("====Fin de lecture du fichier===");
}catch(IOException ioe){
System.out.println("????? Erreur d'entrée/Sortie????");
}}
<<Interface>> <<interface>>
Object
Serializable Comparable<File>
File
Flux d'E/S 43
Terminer la hiérachie de la Classe Reader
<<Interface>> <<interface>>
Object
Closeable Readable
L.HASSOUNI 87
L.HASSOUNI 88
Flux d'E/S 44
Les Collections
en Java
L. HASSOUNI 2
Collections 1
Hiérarchie du Framework des Collections
L. HASSOUNI 3
SortedSet TreeSet
Collection AbstractCollection
Vector Stack
List AbstractList
ArrayList
AbstractSequentialList LinkedList
Deque
L. HASSOUNI 4
Collections 2
Interfaces et classes du Framework collection
• Une interface du Framework collection représente un type spécifique
de structure de données.
• L'interface List spécifie un objet collection de type liste. Les éléments
d'une liste peuvent se dupliquer.
• L'interface set spécifie un objet collection de type ensemble. Les
éléments d'un ensemble ne doivent pas se dupliquer.
• L'interface Queue permet de spécifier une file ou pile.
• L'interface Map spécifie un objet collection dont chaque élément est
une paire <clé, valeur> qui associe une clé à une valeur.
L. HASSOUNI 5
L. HASSOUNI 6
Collections 3
L'interface <<Collection>>
• L'interface Collection est la racine du Framework des collections. Elle
définit une collection générique.
• Le Framework des collections ne fournit pas de classes qui
implémente l'interface Collection.
• L'interface Collection définit le type collection le plus générique et
peut être passé comme paramètre aux méthodes.
• L'interface Collection déclare un ensemble de méthodes qui sont
héritées par tous les autres interfaces collections.
L. HASSOUNI 7
<<interface>>
<<interface>>
Méthode de l'interface Iterable Collection<T>
Collections 4
API Collection
• Les méthodes de l'interface Collection peuvent être réparties en les
classes suivantes:
Opérations basiques
Opérations vrac
Opérations d'agregats
Opérations tableaux
Opérations de comparaison
L. HASSOUNI 9
void clear()
Removes all of the elements from this collection (optional operation).
boolean contains(Object o)
Returns true if this collection contains the specified element.
boolean remove(Object o)
Removes a single instance of the specified element from this collection, if it is present (optional operation).
boolean isEmpty()
Returns true if this collection contains no elements.
int size()
Returns the number of elements in this collection.
L. HASSOUNI 10
Collections 5
package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;
if(noms.isEmpty()){
System.out.println("Collection vide");
}else{
System.out.println("Collection non vide");
}
noms.add("Moha");
noms.add("Toto");
noms.add("Manolo");
noms.add("Moha");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
L. HASSOUNI 11
noms.remove("Manolo");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
if(noms.contains("Manolo")){
System.out.println("Manolo est contenu dans la liste");
}else{
System.out.println("Manolo n'est pas contenu dans la liste");
}
noms.remove("Moha");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
noms.clear();
System.out.println("Elements : " + noms + " Taille : " + noms.size());
}
}
Résultats exécution:
Collectioon vide
Elements : [Moha, Toto, Manolo, Moha] Taille : 4
Elements : [Moha, Toto, Moha] Taille : 3
Manolo n'est pas contenu dans la liste
Elements : [Toto, Moha] Taille : 2
Elements : [] Taille : 0
L. HASSOUNI 12
Collections 6
package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;
public class OperationsBasiques {
public static void main(String[] args) {
Collection<String> noms = new ArrayList<>();
if(noms.isEmpty()){ System.out.println("Collectioon vide"); }
else{System.out.println("Collectioon non vide"); }
noms.add("Moha");
noms.add("Toto");
noms.add("Manolo");
noms.add("Moha");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
noms.remove("Manolo");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
if(noms.contains("Manolo")){ System.out.println("Manolo est contenu dans la liste"); }
else{System.out.println("Manolo n'est pas contenu dans la liste"); }
noms.remove("Moha");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
noms.clear();
System.out.println("Elements : " + noms + " Taille : " + noms.size());
}
}
L. HASSOUNI 13
boolean retainAll(Collection<?> c)
Retains only the elements in this collection that are contained in the specified collection (optional operation).
boolean containsAll(Collection<?> c)
Returns true if this collection contains all of the elements in the specified collection.
boolean removeAll(Collection<?> c)
Removes all of this collection's elements that are also contained in the specified collection (optional operation).
L. HASSOUNI 14
Collections 7
package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;
sportifs.add("Aouita");
sportifs.add("Moutawakkil");
footballeurs.add("Zaki");
footballeurs.add("Bouderbala");
joueursTennis.add("El Aynaoui");
joueursTennis.add("Arazi");
joueursTennis.add("Alami");
L. HASSOUNI 15
sportifs.addAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
if(sportifs.containsAll(footballeurs)){
System.out.println("Les footballeurs sont inclus dans la liste des sportifs");
}
sportifs.retainAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.retainAll(joueursTennis);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.addAll(footballeurs);
sportifs.addAll(joueursTennis);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.removeAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
Collections 8
Exécution
Sportifs : [Aouita, Moutawakkil] NbSportifs : 2
Sportifs : [Aouita, Moutawakkil, Zaki, Bouderbala] NbSportifs : 4
Les ffotballeurs sont inclus dans la liste des sportifs
Sportifs : [Zaki, Bouderbala] NbSportifs : 2
Sportifs : [] NbSportifs : 0
Sportifs : [Zaki, Bouderbala, El Aynaoui, Arazi, Alami] NbSportifs : 5
Sportifs : [El Aynaoui, Arazi, Alami] NbSportifs : 3
Sportifs : [El Aynaoui] NbSportifs : 1
L. HASSOUNI 17
package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;
public class OperationsVrac {
public static void main(String[] args){
Collection<String> sportifs = new ArrayList<String>();
Collection<String> footballeurs = new ArrayList<>();
Collection<String> joueursTennis = new ArrayList<String>();
sportifs.add("Aouita");
sportifs.add("Moutawakkil");
footballeurs.add("Zaki");
footballeurs.add("Bouderbala");
joueursTennis.add("El Aynaoui");
joueursTennis.add("Arazi");
joueursTennis.add("Alami");
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.addAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
if(sportifs.containsAll(footballeurs)){
System.out.println("Les ffotballeurs sont inclus dans la liste des sportifs");
}
sportifs.retainAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.retainAll(joueursTennis);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.addAll(footballeurs);
sportifs.addAll(joueursTennis);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.removeAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.removeIf((String e)->{return e.length()<6;});
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
}}
L. HASSOUNI 18
Collections 9
Méthodes pour opérations de comparaison
boolean equals(Object o)
Compares the specified object with this collection for equality.
int hashCode()
Returns the hash code value for this collection.
package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;
public class OperationsComparaison {
public static void main(String[] args){
Collection<String> sportifs = new ArrayList<>();
Collection <String> joueursTennis = new ArrayList<>();
sportifs.add("El Aynaoui");
sportifs.add("Arazi");
sportifs.add("Alami");
joueursTennis.add("El Aynaoui");
joueursTennis.add("Arazi");
L. HASSOUNI 19
if(sportifs.equals(joueursTennis)){
System.out.println("sportifs = joueursTennis");
}else{
System.out.println("sportifs # joueursTennis");
} Exécution
joueursTennis.add("Alami"); sportifs # joueursTennis
if(sportifs.equals(joueursTennis)){ sportifs = joueursTennis
System.out.println("sportifs = joueursTennis"); 189160881
}else{ 189160881
System.out.println("sportifs # joueursTennis"); -1416950800
}
System.out.println(sportifs.hashCode());
System.out.println(joueursTennis.hashCode());
int tothc = 0;
for(String e : sportifs){
tothc += e.hashCode();
}
System.out.println(tothc);
}
}
L. HASSOUNI 20
Collections 10
package collectionbasicop; Exécution
import java.util.ArrayList; sportifs # joueursTennis
import java.util.Collection; sportifs # joueursTennis
public class OperationsComparaison2 { -1183176409
public static void main(String[] args){ -1874243739
Collection<StringBuilder> sportifs = new ArrayList<>(); -80390400
Collection <StringBuilder> joueursTennis = new ArrayList<>();
sportifs.add(new StringBuilder("El Aynaoui"));
sportifs.add(new StringBuilder("Arazi"));
sportifs.add(new StringBuilder("Alami"));
joueursTennis.add(new StringBuilder("El Aynaoui"));
joueursTennis.add(new StringBuilder("Arazi"));
if(sportifs.equals(joueursTennis)){System.out.println("sportifs = joueursTennis");}
else{System.out.println("sportifs # joueursTennis");}
joueursTennis.add(new StringBuilder("Alami"));
if(sportifs.equals(joueursTennis)){System.out.println("sportifs = joueursTennis");}
else{System.out.println("sportifs # joueursTennis");}
System.out.println(sportifs.hashCode());
System.out.println(joueursTennis.hashCode());
int tothc = 0;
for(StringBuilder e : sportifs){tothc += e.hashCode();}
System.out.println(tothc);
}}
L. HASSOUNI 21
L. HASSOUNI 22
Collections 11
Exécution
package collectionbasicop; El Aynaoui
import java.util.ArrayList; Arazi
import java.util.Collection; Alami
public class OperationsToArray { ================
public static void main(String[] args){ El Aynaoui
Collection<String> sportifs = new ArrayList<>(); Arazi
sportifs.add("El Aynaoui"); Alami
sportifs.add("Arazi");
sportifs.add("Alami");
System.out.println("==================================");
String[] stringArraySportifs = sportifs.toArray(new String[sportifs.size()]);
for(String e : stringArraySportifs){System.out.println(e);}
}
}
L. HASSOUNI 23
L. HASSOUNI 24
Collections 12
Méthodes pour parcourir (ou travaerser) une collection
Iterator<E> iterator()
Returns an iterator over the elements in this collection.
L. HASSOUNI 25
API Iterator
default void forEachRemaining(Consumer<? super E> action)
Performs the given action for each remaining element until all elements have been processed or the action throws an
exception.
boolean hasNext()
Returns true if the iteration has more elements.
E next()
L. HASSOUNI 26
Collections 13
• Une collection possède la méthode Iterator<E> iterator() qui lui
permet d'obtenir un objet Iterator pour parcourir tous les éléments
de la dite collection.
• Un objet Iterator peut exécuter les méthodes de l'interface Iterator.
• Ces méthodes, comme le montre le tableau API Iterator, sont :
• hasNext() : teste s'il y a un élément qui n'a pas été accédé.
• next() : retourne l'élément suivant de la collection. Nous devons toujours
exécuter next() après le succès d'un hasNext(), sinon next() lance l'exception
NoSuchElementException.
• Remove() : supprime l'élément de la liste qui vient d'être retourné par next().
Remove() doit être appelé une seule fois pour chaque appel de next().
Si la méthode remove() est appellee plus d'une fois pour un appel de next(),
ou avant le premier appel de next(), elle lance l'exception
IllegalStateException.
Le support de la methods remove() est optionnel. Remove() peut lancer
l'exception UnsupportedOperationException.
L. HASSOUNI 27
sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");
Collections 14
Suppression d'éléments d'une collection : Iterator, remove()
package collectioniterator;
import java.util.ArrayList; Exécution
import java.util.Collection; Aouita
import java.util.Iterator; Guerrouj
public class CollectionIteratorRemove { Bidouane
public static void main(String[] args){ []
Collection<String> sportifs = new ArrayList<>();
• Remarque :
sportifs.add("Aouita");
sportifs.add("Guerrouj"); • Un Iterator est un objet à
sportifs.add("Bidouane"); une seule utilisation. Il ne
peut pas être réinitialisé
Iterator<String> sportifsIterator = sportifs.iterator(); pour parcourir la collection
while(sportifsIterator.hasNext()){ une nouvelle fois.
String nom = sportifsIterator.next(); • Pour parcourir la collection
System.out.println(nom); une nouvelle fois, il faut
sportifsIterator.remove(); créer un nouveau Iterator
} avec la méthode iterator()
System.out.println(sportifs); de l'objet collection.
}
}
L. HASSOUNI 29
L. HASSOUNI 30
Collections 15
Parcours d'une collection avec la boucle for-each
package collectioniterator; Aouita
import java.util.ArrayList; Guerrouj
import java.util.Collection; Bidouane
import java.util.Iterator;
Exception ConcurrentModificationException
package collectioniterator;
java.util.ConcurrentModificationException
Aouita
Exécution
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.ConcurrentModificationException;
public class CollectionForEachLoopRemove {
public static void main(String[] args){
Collection<String> sportifs = new ArrayList<>();
sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");
try{
for (String elt : sportifs){
System.out.println(elt);
sportifs.remove(elt);
}
}catch(ConcurrentModificationException e){
System.out.println(e);
}
}
}
L. HASSOUNI 32
Collections 16
Application d'une action sur chaque élément d'une collection
iterator.forEachRemaining(action)
package collectioniterator;
Exécution
import java.util.ArrayList;
import java.util.Collection; Aouita
import java.util.Iterator; Guerrouj
Bidouane
public class CollectionIteratorForEachRemaining {
public static void main(String[] args){
Collection<String> sportifs = new ArrayList<>();
sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");
}
L. HASSOUNI 33
}
Représente une opération qui accepte un seul argument et ne retourne pas de résultat.
Comme tout interface fonctionnel, il peut être cible d'une affectation par une lambda expression
ou une référence de méthode "method reference".
L. HASSOUNI 34
Collections 17
Application d'une action sur chaque élément d'une collection
iterator.forEachRemaining(action)
package collectioniterator;
import java.util.ArrayList;
import java.util.Collection; Exécution
import java.util.Iterator;
Elt :Aouita Long : 6
public class CollectionIteratorForEachRemaining2 { Elt :Guerrouj Long : 8
public static void main(String[] args){ Elt :Bidouane Long : 8
Collection<String> sportifs = new ArrayList<>();
sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");
L. HASSOUNI 36
Collections 18
package collectioniterator;
import java.util.ArrayList;
import java.util.Collection;
sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");
sportifs.forEach(System.out::println);
System.out.println("==============================");
sportifs.forEach((String e)->{System.out.println("Elt :" + e +
"\tLong : "+e.length());});
}
}
L. HASSOUNI 37
<<interface>>
Iterable<T>
Collection List
<<interface>>
• Une Liste est une collection non ordonnée d'objets Collection<T>
définie par l'interface List du framework Collection.
• Une liste peut avoir des éléments duppliqués. <<interface>>
Elle peut aussi stocker plusieurs valeurs null. List<T>
Collections 19
Méthodes spécifiques à une liste(1)
void add(int index, E element)
Inserts the specified element at the specified position in this list (optional operation).
int indexOf(Object o)
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain
the element.
int lastIndexOf(Object o)
Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain
the element.
L. HASSOUNI 39
E remove(int index)
Removes the element at the specified position in this list (optional operation).
boolean removeAll(Collection<?> c)
Removes from this list all of its elements that are contained in the specified collection (optional operation).
Collections 20
Méthodes spécifique à une liste(3)
default void replaceAll(UnaryOperator<E> operator)
Replaces each element of this list with the result of applying the operator to that element.
L. HASSOUNI 41
ArrayList vs LinkedList
• ArrayList et LinkedList sont deux classes du Framework Collection qui implémentent
l'interface List.
• Une ArrayList est stokée dans un tableau dynamique.
• Une LinkedList est stockée sous forme de liste chaînée.
• Une ArrayList offre de meilleures performances lorsqu'on accède fréquemment aux
éléments de la liste. L'accès aux éléments se fait plus rapidément puisqu'une ArrayList
est sauvegardée dans un tableau.
• L'ajout et la suppression d'un élément d'une ArrayList se fait plus lentement à moins que
l'opération ne s'effectue à la fin de la liste, ceci parce qu'une ArrayList doit effectuer une
copie de tableau interne pour garder les éléments en séquence.
• Une LinkedList offre de meilleures performances qu'une ArrayList pour les opérations
d'ajout et de suppression à partir du milieu de la liste. Cependant, une LinkedList est plus
lente pour accéder aux éléments à moins que ça se passe en tête de la liste.
L. HASSOUNI 42
Collections 21
package ListExemples;
import java.util.ArrayList;
import java.util.List;
public class ListExemple01 {
public static void main(String[] args) {
List<String> langages = new ArrayList<>();
langages.add("C");
langages.add("C++");
langages.add("Java");
L. HASSOUNI 44
Collections 22
<<interface>>
Parcours d'une liste avec ListIterator Iterator<T>
boolean hasPrevious()
Returns true if this list iterator has more elements when traversing the list in the reverse direction.
int nextIndex()
Returns the index of the element that would be returned by a subsequent call to next().
E previous()
Returns the previous element in the list and moves the cursor position backwards.
int previousIndex()
Returns the index of the element that would be returned by a subsequent call to previous().
Void set(E e)
Replaces the last element returned by next() or previous() with the specified element (optional operation).
L. HASSOUNI 46
Collections 23
Parcours d'une liste dans les deux directions avec ListIterator
package ListExemples;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListListIterator {
public static void main(String[] args) {
List<String> langagesFonctionnels = new ArrayList<>();
langagesFonctionnels.add("Lisp");
langagesFonctionnels.add("Prolog");
langagesFonctionnels.add("Clojure");
langagesFonctionnels.add("Haskel");
System.out.println("Langages: " + langagesFonctionnels);
ListIterator<String> iteratorGlobal = langagesFonctionnels.listIterator();
Collections 24
La partie qui suit est en cours
de modification
L. HASSOUNI 49
L. HASSOUNI Page 50
Collections 25
L. HASSOUNI Page 51
L. HASSOUNI 52
Collections 26
Linterface Set
• un Set est une collection non ordonnée
• Il ne contient pas des éléments en double
L. HASSOUNI Page 53
Sets
• HashSet: Stocke les données dans une table de hachage (Hash
Table)
• TreeSet: Stocke les données dans un arbre Binaire
• Les implementations arrangent ses
éléments de manière à rendre efficace
les opérations d’ajout et de retrait.
L. HASSOUNI Page 54
Collections 27
Concept de table de hachage (Hash Table)
L. HASSOUNI Page 55
Méthode hashCode
• La méthode hashCode calcule un entier à partir des attributs de
l’élément
• Si plusieurs éléments ont le même hash code, ils sont stockés dans une
Linked list.
L. HASSOUNI Page 56
Collections 28
Concept d’arbre binaire (Tree)
• Les éléments sont gardés dans un ordre trié
• Les noeuds ne sont pas rangés dans un ordre linéaire, mais
dans une structure d’arbre.
• Pour utiliser un TreeSet, il doit être possible de comparer les
éléments et de determiner lequel est “plus grand”
L. HASSOUNI Page 57
TreeSet
• Utiliser TreeSet pour les classes qui implémentent l’interface
Comparable
• String et Integer, par exemple
• Les noeuds sont rangés dans un format “d’arbre binaire” pour que chaque
noeud “parent” ait au plus deux noeuds enfants.
• Le noeud de gauche a toujours une valeur inférieure
• Le noeud de droite a toujours une valeur supérieure
L. HASSOUNI Page 58
Collections 29
Iterators et Sets
• Iterators sont aussi utilisés pour traiter les Sets
• hasNext retourne true s’il ya un élément suivant
• next retourne une référence vers la valeur de l’élément suivant
• add ne peut pas utilisé avec un iterator pour TreeSet et HashSet
Iterator<String> iter = names.iterator();
while (iter.hasNext())
for (String name : names)
{
{
String name = iter.next();
// Do something with name
// Do something with name
}
}
• Noter que les éléments ne sont pas retrouvés dans l’ordre de leur
insertion.
• Ils sont retrouvés dans l’ordre dans lequel ils rangés dans le Set:
• Ordre aléatoire pour un HashSet
• Ordre trié pour un TreeSet
L. HASSOUNI Page 59
L. HASSOUNI Page 60
Collections 30
Comment travailler avec les Sets(2)
L. HASSOUNI Page 61
SpellCheck.java (1)
L. HASSOUNI Page 62
Collections 31
SpellCheck.java (2)
L. HASSOUNI Page 63
Astuce de programmation
Pour mainpuler les structures de données, il est
recommandé d’utiliser des références vers des types
interface
Il est considéré comme meilleur style de programmation de
stocker une reference à un HashSet ou TreeSet dans une
variable de type Set.
L. HASSOUNI 64
Collections 32
Les Maps
• Une Map permet d’associer un ensemble de clés à une
collection d’objets.
• Les classes HashMap et TreeMap implémentent toutes les
deux l’interface Map.
L. HASSOUNI Page 65
Maps
Key Value Key Value
L. HASSOUNI Page 66
Collections 33
Paires (clé, Valeur) dans une Maps
• Chaque clé est associée à une valeur
L. HASSOUNI Page 67
L. HASSOUNI Page 68
Collections 34
Itération avec les Maps
• Pour effectuer une itération avec une Map, utiliser la
méthode keySet pour obtenir la liste des clés:
Pour retrouver toutes les valeurs dans une Map, effectuer une
iteration sur l’ensemble des clés et retrouver la valeur qui correspond
à chaque clé.
L. HASSOUNI Page 69
MapDemo.java
L. HASSOUNI Page 70
Collections 35
Fonctions de hachage
• Le hachage peut être utilisé pour retrouver rapidement les
éléments d’un ensemble, sans procéder à une recherche linéaire
en parcourant tous les éléments.
• Une méthode hashCode calcule et retourne une valeur entière:
le code de hachage (hash code).
• Il est souhaitable que la méthode hashCode génère des codes de
hachage differents pour deux objets différents
• Puisque le hachage est si important, la classe Object possède la méthode
hashCode qui calculie un code de hachage pour n’importe quell objet x.
int h = x.hashCode();
L. HASSOUNI Page 71
int h = 0;
for (int i = 0; i < s.length(); i++)
{
h = h + s.charAt(i);
}
L. HASSOUNI Page 72
Collections 36
Calcul des Hash Codes
• Avec cette méthode, une String et sa permutation (tel que "eat" et "tea")
auront le même code de hachage
• La classe String de la librairie Java définit la méthode hashCode comme suit:
L. HASSOUNI Page 73
L. HASSOUNI Page 74
Collections 37
Calcul du Hash Code d’un objet
• Vous devez avoir une bonne méthode hashCode pour
stocker efficacement vos objets
• Redéfinissez la méthode hashCode dans votre classe en
combinant les hash codes des variables d’instance, puis
combinez ces hash codes en utilisant un nombre premier
comme multiplicateur de hachage.
L. HASSOUNI Page 76
Collections 38
Listes, files et files prioritaires
• Piles sont utilisées pour réaliser les opérations du type “Annuler” (La dernière
operation en premier)
• files sont utilisées pour gérer les files comme la queue de clients d’une
banque ou d’un magasin
• Files prioritaires pour gérer des tâches avec priorités (suppriment les tâches
moins urgentes en premier).
L. HASSOUNI Page 77
Collections 39
Utilisation des Files et Files prioritaires
L. HASSOUNI Page 79
Files prioritaires
• Une file prioritaire collecte des éléments dont chacun a
une priorité.
• Exemple: Une collection de tâches, dont chacune a une
priorité (des tâches plus urgentes que d’autres)
• Ce n’est pas une liste FIFO
PriorityQueue<WorkOrder> q = new PriorityQueue<WorkOrder>();
q.add(new WorkOrder(3, "Shampoo carpets"));
q.add(new WorkOrder(1, "Fix broken sink"));
q.add(new WorkOrder(2, "Order cleaning supplies"));
Priorité Tâche
• Les objets qui ont une faible priorité(1) sont enlevés en
premier.
L. HASSOUNI Page 80
Collections 40
Applications des piles et files
L. HASSOUNI Page 81
L. HASSOUNI Page 82
Collections 41
Exemple d’utilisation de la pile
• L’exemple ci-dessous est une expression mathématique qui
utilise trois types de parenthèses
L. HASSOUNI Page 83
L. HASSOUNI Page 84
Collections 42
Evaluation des expressions en notation polonaise
Si on rencontre un nombre
empilez le dans la pile
Sinon si on rencontre un opérateur
dépiler deux valeurs de la pile
les combinez avec l’opérateur
empilez le résultat dans la pile
Sinon si on arrive à la fin de l’expression
dépiler et afficher le résultat.
L. HASSOUNI Page 85
L. HASSOUNI Page 86
Collections 43
Calculator.java (1)
L. HASSOUNI Page 87
Calculator.java (2)
L. HASSOUNI Page 88
Collections 44
Evaluation des expressions algébriques
• Peut être réalisée en utilisant deux piles:
1) Une 1ère pile pour les nombres
2) Un 2ème pile pour les Opérateurs et parenthèses
• Premier Exemple: 3 + 4
L. HASSOUNI Page 89
• Second Exemple: 3 x 4 + 5
L. HASSOUNI Page 90
Collections 45
Expressions et priorité (1)
• Troisième Exemple: 3 + 4 x 5
L. HASSOUNI Page 91
L. HASSOUNI Page 92
Collections 46
Expressions avec Parenthèses (1)
• Quatrième Exemple: 3 x ( 4 + 5 )
L. HASSOUNI Page 93
L. HASSOUNI Page 94
Collections 47
Algorithme
If you read a number
Push it on the number stack.
Else if you read a (
Push it on the operator stack.
Else if you read an operator op
While the top of the stack has a higher precedence than op
Evaluate the top.
Push op on the operator stack.
Evaluate the Top:
Else if you read a )
Pop two numbers off the
While the top of the stack is not a (
Evaluate the top. number stack.
Pop the ). Pop an operator off the
Else if there is no more input operator stack.
While the operator stack is not empty Combine the numbers with
Evaluate the top. that operator.
Push the result on the
number stack.
L. HASSOUNI Page 95
L. HASSOUNI Page 96
Collections 48
Etapes pour choisir une Collection
3) Determiner si l’ordre des élement ou des clés importe
• Les éléments ou clés doivent être triés
• Uiliser une TreeSet ou TreeMap. Aller à l’étape 6
• Les élements doivent être rangés dans le même ordre dans
lequel ils ont été insérés
• Votre choix est maintenant limité à LinkedList ou ArrayList
• L’ordre des éléments n’importe pas
• Si vous avez choisi une Map à l’étape1, utilisez une HashMap et allez
à l’étape 5
L. HASSOUNI Page 97
L. HASSOUNI Page 98
Collections 49
Etapes pour choisir une Collection
L. HASSOUNI Page 99
API
Collections 50
Stack : API
Class Stack<E>
•java.lang.Object
•java.util.AbstractCollection<E>
•java.util.AbstractList<E>
•java.util.Vector<E>
•java.util.Stack<E>
L. HASSOUNI 102
Collections 51
Constructor and Description
Stack() : Creates an empty Stack.
Methods
Modifier and Type Method and Description
boolean empty()Tests if this stack is empty.
E peek()Looks at the object at the top of this stack without
removing it from the stack.
E pop()Removes the object at the top of this stack and
returns that object as the value of this function.
E push(E item)Pushes an item onto the top of this stack.
L. HASSOUNI 103
Map
Nested Classes
Modifier and Type Interface and Description
static interface Map.Entry<K,V>A map entry (key-value pair).
L. HASSOUNI 104
Collections 52
Map Methods(1)
Modifier and Type Method and Description
void clear()Removes all of the mappings from this map (optional operation).
default V compute(K key, BiFunction<? super K,? super V,?
extends V> remappingFunction)Attempts to compute a mapping for the
specified key and its current mapped value (or null if there is no current
mapping).
default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)If
the specified key is not already associated with a value (or is mapped to null),
attempts to compute its value using the given mapping function and enters it
into this map unless null.
default V computeIfPresent(K key, BiFunction<? super K,? super V,?
extends V> remappingFunction)If the value for the specified key is present and
non-null, attempts to compute a new mapping given the key and its current
mapped value.
boolean containsKey(Object key)Returns true if this map contains a mapping for the
specified key.
boolean containsValue(Object value)Returns true if this map maps one or more keys to
the specified value.
L. HASSOUNI 105
Map Methods(2)
Set<Map.Entry<K,V>> entrySet()Returns a Set view of the mappings contained in this map.
boolean equals(Object o)Compares the specified object with this map for equality.
default void forEach(BiConsumer<? super K,? super V> action)Performs the given action for
each entry in this map until all entries have been processed or the action throws
an exception.
V get(Object key)Returns the value to which the specified key is mapped, or nullif
this map contains no mapping for the key.
default V getOrDefault(Object key, V defaultValue)Returns the value to which the
specified key is mapped, ordefaultValue if this map contains no mapping for the
key.
int hashCode()Returns the hash code value for this map.
boolean isEmpty()Returns true if this map contains no key-value mappings.
Set<K> keySet()Returns a Set view of the keys contained in this map.
default V merge(K key, V value, BiFunction<? super V,? super V,?
extends V> remappingFunction)If the specified key is not already associated
with a value or is associated with null, associates it with the given non-null
value.
L. HASSOUNI 106
Collections 53
Map Methods(3)
V put(K key, V value)Associates the specified value with the specified key in this map (optional
operation).
void putAll(Map<? extends K,? extends V> m)Copies all of the mappings from the specified map
to this map (optional operation).
default V putIfAbsent(K key, V value)If the specified key is not already associated with a value (or is
mapped to null) associates it with the given value and returnsnull, else returns the current
value.
V remove(Object key)Removes the mapping for a key from this map if it is present (optional
operation).
default boolean remove(Object key, Object value)Removes the entry for the specified key only if it is currently
mapped to the specified value.
default V replace(K key, V value)Replaces the entry for the specified key only if it is currently mapped
to some value.
default boolean replace(K key, V oldValue, V newValue)Replaces the entry for the specified key only if
currently mapped to the specified value.
default void replaceAll(BiFunction<? super K,? super V,? extends V> function)Replaces each entry's value
with the result of invoking the given function on that entry until all entries have been
processed or the function throws an exception.
int size()Returns the number of key-value mappings in this map.
Collection<V> values()Returns a Collection view of the values contained in this map.
L. HASSOUNI 107
Bien à vous
A terminer
Collections 54