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+")"); } }