TP 1 – Threads
Exercice 1
1. Ecrire une classe Compteur qui possède un nom et qui compte jusqu’à n en affichant à chaque fois son nom et le nombre en cours, dans une fonction « public void run()« .
Il marque une pause aléatoire entre chaque nombre (de 0 à 2000 millisecondes par exemple).
Une fois terminé il indique qu’il a terminé (toujours en affichant son nom).
2. Dans la fonction main, lancez plusieurs compteurs à la suite. Que se passe-t-il ? (évident)
public class Compteur01 {
private String nom;
private int max;
public Compteur01(String nom, int max) {
super();
this.nom = nom;
this.max = max;
}
public void run() {
for (int i=1; i<this.max; i++) {
System.out.println(this.nom+" "+i);
try {
Thread.sleep((int) (Math.random() * 2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.nom+" terminé.");
}
public static void main(String[] args) {
Compteur01 c1=new Compteur01("Bob",8);
Compteur01 c2=new Compteur01("Jon",8);
c1.run();
c2.run();
}
}
3. Modifier la classe pour en faire un thread (attention il ne fait plus appeler directement la méthode run()).
public class Compteur02 extends Thread {
private String nom;
private int max;
public Compteur02(String nom, int max) {
super();
this.nom = nom;
this.max = max;
}
public void run() {
for (int i=1; i<this.max; i++) {
System.out.println(this.nom+" "+i);
try {
Thread.sleep((int) (Math.random() * 2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.nom+" terminé.");
}
public static void main(String[] args) {
Compteur02 c1=new Compteur02("Bob",8);
Compteur02 c2=new Compteur02("Jon",8);
c1.start();
c2.start();
}
}
4. Ajouter une ligne pour afficher « Tout est terminé », à la fin de la méthode main. Que se passe-t-il ?
...
c1.start();
c2.start();
System.out.println("Tout est terminé.");
Comment faire ?
...
c1.start();
c2.start();
try {
c1.join();
c2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Tout est terminé.");
}
}
5. Le langage JAVA propose le mécanisme des interfaces. Modifiez ce programme pour implémenter l’interface Runnable au lieu d’hériter de Thread.
Exercice 2
On donne la classe suivante, qui permet de gérer le solde d’un compte bancaire, en effectuant des débits et des crédits.
public class CompteBancaire {
private int solde = 0;
public int getSolde() {
return solde;
}
public void debite(int op) {
System.out.println("Débit de "+op);
this.solde-=op;
}
public void credite(int op) {
System.out.println("Crédit de "+op);
this.solde+=op;
}
}
La classe OperationNulle lance un ou plusieurs threads qui exécutent des opérations s’annulant (crédit puis débit de la même somme).
public class OperationsNulles extends Thread {
private CompteBancaire compte;
private static int nbTh = 20;
private int ID ;
public OperationsNulles(CompteBancaire compte, int i) {
super();
this.compte = compte;
this.ID=i;
}
public void run() {
while (true) {
int s = (int) (Math.random() * 1000);
compte.credite(s);
compte.debite(s);
System.out.println("solde "+compte.getSolde()+ " (opération "+this.ID+")");
}
}
public static void main(String[] args) {
CompteBancaire compte = new CompteBancaire();
OperationsNulles operations[]=new OperationsNulles[nbTh];
for (int i = 0; i < nbTh; i++) {
operations[i] = new OperationsNulles(compte,i);
operations[i].start();
}
}
}
Que se passe-t-il lorsqu’on lance plusieurs de ces threads en même temps ?
Comment corriger.
public void run() {
while (true) {
int s = (int) (Math.random() * 1000);
synchronized (compte) {
compte.credite(s);
compte.debite(s);
}
System.out.println("solde "+compte.getSolde()+ " (opération "+this.ID+")");
}
}