Java

Transcription

Java
La programmation concurrente
Java
page : 1
Introduction
„
Dans de nombreux contextes, il est
intéressant d'effectuer plusieurs traitements
distincts en même temps
‹Application réseau
„
En même temps ne signifie pas une
simultanéité parfaite
‹Il est possible de simuler l'exécution simultanée de
deux traitements en leur permettant d'avoir accès,
chacun à leur tour, au processeur
‹On dit que les traitements sont CONCURRENTS
z Puisqu'ils sont en concurrence permanent pour
l'accès au processeur
Java
page : 2
Prog. Concurrente en Java
„
Deux mécanismes permettent
l'ordonnancement automatique des traitements
‹La concurrence entre commandes du système
correspondant à des processus
‹La concurrence entre processus léger (threads) de la
machine virtuelle, qui correspondent à différents traitements
au sein d'un même processus
„
Ces mécanismes créent de nouveaux
problèmes liés à :
‹La synchronisation,
‹L'exclusion mutuelle
‹La vivacité
Java
page : 3
Processus Vs Threads
Java
page : 4
Les processus
Java
page : 5
Les processus
„
Processus : unité d'exécution gérée par le
système
„
En Java, il est possible d'accéder à ce
mécanisme pour gérer la concurrence via les
classes
‹Runtime représentant un environnement d'exécution
‹Process représentant un processus
‹Les possibilités d'interaction sont limitées et cela interdit
une gestion fine de la concurrence entre les processus
‹En java : il est possible de lancer l'exécution de
commandes quelconques en concurrence avec une
application Java
Java
page : 6
Créer un processus
„
A toute application Java est associé un objet
de contrôle de son unité d'exécution :
‹Objet de la classe Runtime
‹Cet objet est obtenu par la méthode statique
Runtime.getRuntime();
„
Cet objet permet d'obtenir des informations
‹Concernant la mémoire
z totalMemory()
z freeMemory()
‹D'appeler le ramasse-miettes
z gc()
‹De terminer l'application courante
z exit( int val )
Java
page : 7
Créer un processus
„
L'objet Runtime permet de
‹Créer et démarrer l'exécution d'une autre commande
„
Démarrer l'exécution d'une autre commande
‹Méthodes surchargées exec() de l'objet runtime
z Le processus appelant : processus PERE
z Le processus appelé : processus FILS
‹Exemples:
Runtime.getRuntime.exec("javac TP1.java");
Runtime.getRuntime.exec( new String[] {
"javac", "TP2.java" } );
z
Java
L'objet retourné est de la classe Process et permet
de contrôler le processus fils
page : 8
Mort d'un processus
„
La méthode destroy()
‹Appelée sur un objet de la classe Process contrôlant un
processus FILS, permet de demander sa terminaison
„
Attente
‹Un processus PERE peut également attendre la mort d'un
processus fils grâce à la méthode waitFor() appliquée à
l'objet processus du fils
‹Cette méthode attend que le processus fils termine (l'attente
est dite BLOQUANTE)
‹Au moment de sa terminaison, un processus retourne un
entier (le paramètre de la méthode exit() de son objet
runtime) dont la valeur peut être obtenue par la méthode
exitValue()
0 pour un processus forcé par destroy()
Java
page : 9
Communiquer par les flots
„
L'objet processus permet également de
récupérer des flots connectés
‹à l'entrée standard
‹à la sortie standard
‹à la sortie erreur
du processus fils
‹La méthode getOutputStream() appelée sur un objet
processus d'un fils permet au processus père de
récupérer un flot en écriture connecté à l'entrée
standard de ce fils
‹Symétriquement, les méthodes getInputStream() et
getErrorStream() retournent des flots en lecture
permettant au père de lire les sorties standard et
d'erreur du processus fils
Java
page : 10
Les Threads
Java
page : 11
Qu'est-ce qu'un thread ?
„
un processus
‹unité d'exécution qui a un but fonctionnel
‹un espace mémoire
‹des lignes de code décrivant son déroulement
„
une routine
‹procédure ou fonction
‹tranche de temps du processus
„
un thread
‹se situe entre les deux
‹sorte de processus à l'intérieur d'un processus
„
appel d'un thread
‹est comme un appel d'une méthode qui rendrait tout
de suite la main, alors qu'elle n'est pas terminée
Java
Les Threads
page : 12
Vous dites que j'en ai déjà utilisé ?
„
le noyau Java s'appuie sur le
multithreading
‹un des threads exécute le programme
‹un autre récupère la mémoire
„
s'il fallait construire un robot imitant l'être
humain, il serait multithread
‹une personne peut
z conduire une voiture
z et parler en même temps
Les Threads
Java
page : 13
intérêt des threads par rapport
aux méthodes ?
„
„
exécuter des tâches en parallèle
exemple : programme gérant plusieurs
voies de communication simultanément
‹OU utiliser des threads
z vous programmer comme si vous n'aviez qu'une
seule voie à traiter à la fois
z et vous lancer autant de threads concurrents qu'il
y a de voies à traiter
‹OU vous n'utilisez pas les threads
z programmation par automate qui examine les
voies les unes après les autres, en sauvegardant
dans un tableau les états correspondants à toutes
les autres voies (DIFFICILE)
Java
Les Threads
page : 14
Intérêt des threads par rapport
aux processus
„
disposer
‹d'un espace mémoire PARTAGE
‹de code PARTAGE
‹de ressources PARTAGEES
„
Le lancement et l'exécution d'un thread
est beaucoup plus économique que
le lancement et l'exécution d'un processus
Les Threads
Java
page : 15
Exemples de threads (1)
class Fable {
static Animal leLievre;
static Animal laTortue;
public static void main (String arg [ ] ) {
leLievre = new Animal (5,"L");
laTortue = new Animal (1,"T");
laTortue.run () ;
leLievre.run () ;
}
}
Java
Les Threads
page : 16
Exemples de threads (2)
class Animal {
int maVitesse;
String monNom;
public Animal (int laVitesse, String leNom) {
monNom = leNom ;
maVitesse = laVitesse ; }
public void sleep (int temps) {
for (int i = 0 ; i <= temps ; i++) {;}
public
}
void run () {
for (int i = 0; i <10 ; i++ ) {
System.out.println(monNom);
sleep (1000/maVitesse); }
System.out.println( "\n" + monNom + " est arrivé"); }
}
Les Threads
Java
page : 17
Exemples de threads (3)
„
résultat
TTTTTTTTTT
T est arrivé
LLLLLLLLL
L est arrivé
„
le lièvre n'a aucune chance d'arriver le
premier
‹le programme commence par la tortue
‹et après l'arrivée de celle-ci s'occupe du lièvre
„
partage de la ressource CPU dans le temps
Tortue
Java
puis
Les Threads
Lièvre
page : 18
Exemple de threads (4)
„
transformation de la classe Animal en thread
class Fable {
static Animal leLievre;
static Animal laTortue;
public static void main (String arg [ ] ) throws
InterruptedException {
leLievre = new Animal (5,"L");
laTortue = new Animal (1,"T");
laTortue.start() ; // lancement du thread
leLievre.start () ;
laTortue.join();// attente de la fin des deux threads
leLievre.join();// avant la sortie du programme
} }
Les Threads
Java
page : 19
Exemple de threads (5)
class Animal
extends Thread {
int maVitesse;
String monNom;
public Animal (int laVitesse, String leNom) {
monNom = leNom ;
maVitesse = laVitesse ; }
public
void run () {
for (int i = 0; i <10 ; i++ ) {
System.out.println(monNom);
try {
sleep (1000/maVitesse);
}
catch (Exception e) {;};
}
System.out.println( "\n" + monNom + " est arrivé"); }
}
Java
Les Threads
page : 20
Exemple de threads (6)
„
L'exécution de ce programme donne alors
le résultat suivant :
TLLLLTLLLLL
L est arrivé
TTTTTTTT
T est arrivé
„
partage de la ressource CPU dans le temps
Lièvre
„
Java
Tortue
L'appel à la méthode start() de la classe Thread démarre
le thread et entraîne l'appel à la méthode run()
Les Threads
page : 21
Je savais bien que l'héritage
multiple me manquerait
„
Si je veux créer un thread qui hérite d'une autre
classe que Thread, par exemple Applet, je ne peux
pas ???
„
Autre mécanisme de lancement des threads
‹fournir au constructeur du thread un objet ( Animal par exemple)
‹exemple :
Thread t = new Thread ( new Animal()) ;
t.start () ;
‹quelle est la méthode de Animal appelée lors du start() ?
z réponse : la méthode run() de Animal
Java
Les Threads
page : 22
L'interface Runnable
„
„
l'interface Runnable décrit les méthodes
que doivent implémenter les objets
pouvant être passés en paramètre des
constructeurs de threads.
une classe qui implémente Runnable a
‹pour devoir de fournir une implémentation de la
méthode run()
‹pour droit d'être passée en paramètre à la création
d'un thread
„
exemple :
class Animal implements Runnable {
.....
public void run () { ... }
}
Les Threads
Java
page : 23
Techniques pour implémenter les
threads
„
Définir une classe qui hérite de la classe Thread
„
Définir une classe qui implémente l'interface
Runnable
et dont une instance est passée en paramètre du
constructeur du Thread
‹Dans les deux cas, la classe doit définir la méthode run(),
appelée lorsqu'on appelle la méthode start() du thread
„
Conseils :
‹hériter de Thread lorsque cela est possible
‹sinon implémenter Runnable lorsque la classe hérite déjà
d'une autre classe
Java
Les Threads
page : 24
Etats d'un thread
„
„
„
les threads sont des objets ayant un attribut
prédéfini : leur état d'exécution
cet attribut est privé
comme les processus, les threads ont un
état relatif à leur exécution
ils peuvent être :
‹créées
‹actifs
‹endormis
‹morts
Les Threads
Java
page : 25
Transitions entre états
new()
créé
start()
wait() sleep() suspend()
actif
endormi
resume()
stop()
stop()
mort
Java
Les Threads
page : 26
Thread créé
„
les threads sont d'abord créés, comme
n'importe quel objet Java:
‹laTortue = new Animal( 1 , "T" );
„
new () crée l'objet,
‹alloue la mémoire nécessaire
‹mais n'alloue pas d'autres ressources
‹le thread est dans les limbes, mais il n'est pas encore
vivant !!!!
Les Threads
Java
page : 27
Thread Actif
„
la méthode start()
‹alloue les différentes ressources nécessaires à
l'exécution du thread
‹et lance la méthode run ()
„
„
le thread devient actif
remarque
‹il ne s'exécute pas en permanence mais dispose
régulièrement d'une tranche de temps
‹les tranches de temps sont brèves ce qui donnent à
l'utilisateur l'illusion d'une exécution simultanée
‹un thread actif est un thread auquel le processeur
alloue régulièrement une tranche de temps
Java
Les Threads
page : 28
Thread endormi
„
un thread endormi ne consomme pas de
ressources machine, mais une fois réveillé il
redeviendra actif
„
plusieurs cas peuvent conduire un thread à l'état
endormi:
‹méthode : sleep( durée)
ours.sleep( hiver )
réveil au bout du temps durée
‹méthode : suspend()
gaston.suspend()
reveil : méthode resume()
gaston.resume()
‹attente d'une ressource système d'E/S
‹attente sur une condition
Les Threads
Java
page : 29
Thread mort
„
La mort intervient de deux façons :
‹fin de la méthode start()
z exemple: leLievre et laTortue
z le thread a terminé ce qu'il avait à faire
‹appel de la méthode stop ()
z intervention extérieure au thread
Java
Les Threads
page : 30
Priorité
Les Threads
Java
page : 31
Priorité
„
définition da la priorité
‹un processus peut être découpé en threads( sousprocessus)
‹parmi ces threads ,certains sont
z plus importants
z ou plus consommateurs de ressources
„
le noyau exécutable de Java implémente
la notion de priorité entre threads
‹ex: le ramasse-miettes a une priorité faible
„
Java
la création d'un thread précise sa priorité
absolue
Les Threads
page : 32
Partage du temps entre threads
„
la partage de temps entre 2 threads de
priorités différentes :
‹tant que le thread de plus haute priorité n'est pas
endormi, il possède les ressources
‹s'il s'endort, il donne à l'autre la possibilité d'utiliser la
ressource CPU
‹s'il se réveille il reprend la ressource
„
le partage de temps entre threads de
même priorité dépend de la machine !!!
Les Threads
Java
page : 33
Les tranches de temps
„
méthode de répartition de la ressource CPU
- par tranche de temps
‹les threads de la plus haute priorité ont chacun leur
tour, quelques millisecondes de temps CPU
„
si ce n'est pas le cas :
‹un thread ayant accaparé la ressource ne la rendra
pas avant de s'endormir !!!!
„
solution : méthode yield()
‹cette méthode permet à un thread de partager la
ressource CPU avec les threads de même priorité
Java
Les Threads
page : 34
Exemple de gestion de priorité (1)
import java.io.*;
class Priorite {
static Animal leLievre ;
static Animal laTortue;
public static void main (String argv [ ] )
throw InterruptedException {
System.out.print ln("prio. max :" + thread.MAX_PRIORITY);
System.out.print ln("prio. min :" + thread.MIN_PRIORITY);
leLievre = new Animal(6, "L");
laTortue = new Animal(2,"T");
leLievre.start();
laTortue.start();
leLievre.join();
laTortue.join();
System.out.println( );
}
}
Java
Les Threads
page : 35
Verrouillage des ressources
Saint Kronisme
Java
Les Threads
page : 36
Verrouillage de ressources (1)
„
conflit de ressources
‹deux threads tentent de mettre à jour le même emplacement de
mémoire en simultanée
„
verrou d'un objet : mot clé "synchronized"
‹une méthode verrouillée ne peut être utilisée que par un seul
thread à la fois
‹exemple :
class Compte {
public synchronized void retrait(double montant) {
solde = solde - montant; }
public synchronized void credit(double montant) {
solde = solde + montant; }
}
Les Threads
Java
page : 37
Verrouillage de ressources (2)
„
„
un objet peut aussi être verrouillé dans une
section de code
exemple :
class Test {
public void fonction(Compte ba) {
synchronized(ba)
{
... je suis seul à accéder
}
}
Java
Les Threads
à l'objet ba
page : 38
Conclusion sur la Synchronisation
„
synchronized nomFonction
ou synchronized(nomObjet)
empêchent :
‹deux threads d'exécuter la même portion de code en
même temps sur le même objet
‹MAIS deux threads peuvent exécuter
z deux méthodes différentes sur le même objet
z ou la même méthode sur deux objets différents
Java
Les Threads
page : 39
Rendez-vous
Java
Les Threads
page : 40
Rendez-vous (1)
„
„
„
les threads peuvent organiser des rendez-vous
entre-eux, en partageant une attente sur un
objet commun
Un ou plusieurs threads attendent qu'ils se passe
quelque chose sur un objet et un autre thread
met fin à leur attente
la classe Object propose trois méthodes :
‹notify() et notifyAll()
‹wait()
‹wait() appelée dans un thread, signifie que le thread va
attendre qu'un autre thread appelle notify() dans une autre
méthode du même objet
Les Threads
Java
page : 41
Rendez-vous (2)
„
Java
exemple :
import java.io.*;
public class ecole {
public static void main( String argv [ ]) {
try {
Notes sex = new Note () ;
Professeur etienne = new Professeur(sex);
Eleve jean = new Eleve (sex, " jean");
jean.start() ;
etienne.start();
jean.join();
etienne.join();
}
catch (Exception e){
System.out.println(e.toString());}
}}
Les Threads
page : 42
Rendez-vous (3)
class Notes {
public synchronized void seFontAttendre() {
try {
wait () ; }
catch( InterruptedException e) {
System.out.println (e.toString () ) ; }
}
public synchronized void etreDiffusees () {
notifyAll() ;
}
}
class Eleves extends Thread {
Notes notes;
String monNom;
Java
Les Threads
page : 43
Rendez-vous (4)
public Eleve (Notes lesNotes, String leNom) {
notes = lesNotes;
monNom = leNom;
}
public void run () {
System.out.println (monNom + " attend sa note) ;
notes.seFontAttendre() ;
System.out.println( monNom +" a eu sa note");
}
}
class Professeur extends Thread {
Notes notes;
public Professeur(Notes lesNotes) { notes= lesNotes; }
public synchronized void run () {
System.out.println("Je vais rendre les notes");
notes.etreDiffusees () ;
}
}
Java
Les Threads
page : 44
Exercice 1
„
Vous devez ordonner les exécutions de 5 processus
légers.
‹Chaque processus léger possède un numéro différent, entre 0 et 4
‹Le processus N ne peut s'exécuter que si un compteur externe est
égal à son numéro
‹Une fois son exécution terminée, le processus léger incrémente le
compteur, modulo le nombre de processus légers et réveille tous les
processus légers afin que le processus léger du numéro suivant
puisse prendre la main
Java
page : 45
Exercice 2
„
Simulation du départ d'une fusée
‹ Le but de cette simulation : simuler le lancement entre l'instant où le chef du
centre déclenche le compte à rebours et l'instant où il allume les réacteurs
de la fusée
‹ La simulation utilise trois objets :
z Un compte à rebours
z Deux équipes (l'équipe météo et l'équipe sécurité) : chaque équipe est
représentée par un objet qui est une instance de la classe Equipe
‹ Après le déclenchement du compte à rebours par le chef du centre les
deux équipes peuvent prendre la décision de retarder le décollage de la
fusée.
‹ Les comportements des deux équipes est régi par deux règles :
z Les deux équipes exécutent des tâches indépendamment les unes des
autres
z Les deux équipes partagent une ressource commune : le compte à
rebours
Java
page : 46
Groupe de threads
Java
page : 47
Groupes de threads (1)
„
chaque thread appartient à un groupe de
threads
‹un groupe est défini par la class ThreadGroup
„
exemple:
ThreadGroup lesAnimaux = new ThreadGroup("Animaux");
Thread Lievre = new Thread (lesAnimaux,"Lievre");
Thread Lapin = new Thread(lesAnimaux,"Lapin");
‹les groupes de threads forment une hiérarchie
‹à sa création un groupe est fils du groupe courant
Java
Groupe de Threads
page : 48
Groupe de threads (2)
„
intérêts des groupes de threads
‹les méthodes
z resume()
z stop ()
z suspend ()
agissent sur les threads du groupe courant et de ses
descendants
‹les méthodes
z getMaxPriority()
z getName()
z getParent()
permettent d'obtenir les valeurs des attributs
décrivants le groupe de threads
‹permet d'effectuer une action sur un ens. de threads
Java
Groupe de Threads
page : 49
Application : programmation
réseau
Java
page : 50
Les sockets
„
Les sockets,
‹mécanismes de communication entre processus,
‹fonctionnent, que les processus soient sur la même
machine ou non
‹Les processus échangent des données à travers un
réseau, local ou distant.
Java
page : 51
Le principe des sockets
„
Le principe des sockets est du type client-serveur:
‹un processus serveur déclare accepter les connexions des
clients,
‹et lorsqu'un client se présente, un socket est créé pour établir le
lien entre les deux.
„
Le mécanisme des sockets n'est pas propre à
Java,
‹mais Java en fournit une implémentation portable, réalisée
grâce aux classes ServerSocket et Socket.
Java
page : 52
ServerSocket
„
Les Constructeurs de la classe ServerSocket :
‹ServerSocket(int port)
‹ServerSocket(int port, int backlog)
‹ServerSocket(int port, int backlog,
InetAddress bindAddr)
‹Le point commun entre ces trois constructeurs est le numéro
de port sur lequel l'instance va "écouter" les requêtes des
clients.
‹Chacun de ces trois constructeurs est susceptible de lever
une exception de type IOException lors de leur appel.
‹Exemple :
try
{
ServerSocket server = new ServerSocket(1515);
} catch(IOException ioe) {}
Java
page : 53
ServerSocket
„
Le deuxième et le troisième constructeur ajoutent un
second paramètre, désigné ici sous le nom de "backlog".
„
lorsqu'un socket serveur reçoit une demande de
connexion, il est possible qu'il ne puisse la résoudre
instantanément. C'est pourquoi le serveur possède une file
d'attente dans laquelle s'alignent les demandes de
connexions.
Dans le cas d'un serveur destiné à héberger un site internet,
des centaines de demandes peuvent affluer
instantanément. Le paramètre backlog est destiné à limiter
la taille de la file d'attente.
Prenons l'exemple suivant:
„
„
try
{
ServerSocket server = new ServerSocket(1515,1);
} catch (IOException ioe) {}
Java
page : 54
Méthode accept()
„
„
La classe ServerSocket contient neuf
méthodes.
La méthode la plus utile est accept()
public Socket accept();
„
Java
Cette méthode permet d'obtenir des
instances de la classe Socket correspondant
aux divers clients connectés à votre serveur.
page : 55
Code du client (1)
Java
„
Le programme client se connecte à un serveur
en indiquant l'adresse de la machine et le port
qu'il demande.
„
Notre exemple met en communication deux
processus sur la même machine, donc
l'adresse de la machine est l'adresse locale et
le port est le numéro choisi par le serveur
(5000).
page : 56
Le schéma de fonctionnement
Serveur
Client
s = ServerSocket(port#)
connexion
c = s.accept()
InputStream
lecture
s = Socket(@IP,port#)
lecture
InputStream
écriture
OutputStream
pipe réseau
OutputStream
écriture
c.close()
s.close()
s.close()
Java
page : 57
Exemple de Serveur Echo
import java.io.*;
import java.net.*;
public class Serveur {
private ServerSocket soquette;
private Socket client;
int nbClients = 0;
public static void main (String [] args) {
new Serveur();
}
Java
page : 58
Exemple de Serveur (2)
public Serveur() {
try {
soquette = new ServerSocket(5000);
while (nbClients < 2) {
nbClients ++;
client =soquette.accept();
PrintStream p =
new PrintStream(client.getOutputStream());
StringBuffer s =
new StringBuffer("Bonjour client");
p.println(s.toString());
client.close();
}
} catch(Exception e) {
System.out.println(e.getMessage());
}
};
}
Java
page : 59
Code du client (3)
import java.io.*;
import java.net.*;
public class Client {
public static void main (String [ ] arg) {
new Client();
}
InetAddress adresse;
Socket soquette;
public Client () {
try {
adresse = InetAddress.getLocalHost ();
soquette = new Socket(adresse,5000);
BufferedReader in = new BufferedReader(
new InputStreamReader( soquette.getInputStream()));
System.out.println(in.readLine());
soquette.close();
}
catch (Exception e) {
System.out.println(e.getMessage());
};
}
Java
page : 60
Servir plusieurs clients
„
Chaque fois que le serveur établi une nouvelle
connexion,
c'est à dire qu'il a accepté une requête,
un nouveau Thread est créé qui sera chargé de
la gestion de la connexion entre le serveur et le
client
„
La boucle principale :
while(true)
{ Socket cl = s.accept();
Thread t = new ThreadEchoHandler( cl );
t.start();
}
Java
page : 61
La classe ThreadEchoHandler
class ThreadEchoHandler extends Thread
{ private Socket cl;
public ThreadEchoHandler(Socket cl){ this.cl = cl; }
public void run() {
try
{ BufferedReader in = new BufferedReader(
new InputStreamReader(cl.getInputStream()));
PrintWriter out = new PrintWriter (
cl.getOutPutStream(), true);
String line;
while((line=in.readLine() != null)
{ traitement de la ligne
}
cl.close();
}
catch(Exception ex) { System.out.println(e.getMessage(); }
}
}
Java
page : 62