:: Enseignements :: Master :: M1 :: 2016-2017 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Thread, Runnable, join, synchronized, interrupt |
Exercice 1 - Hello Thread
On souhaite créer 4 threads (le nombre peut changer) qui exécutent un même
code affichant les nombres de 0 à 5 000.
Histoire de différencier les threads à l'affichage, chaque thread
affichera en plus du nombre courant un numéro (0 pour la première thread,
1 pour la seconde, etc).
Par exemple, on pourra obtenir ce type d'affichage :
...
hello 0 1714
hello 0 1715
hello 0 1716
hello 0 1717
hello 1 1096
hello 1 1097
hello 1 1098
hello 1 1099
...
Rappel: créer un
Runnable se fait en utilisant la syntaxe des lambdas,
comme ceci
Runnable r = () -> {
...
};
-
Rappeler à quoi sert un Runnable ?
-
Ecrire dans un premier temps, une classe HelloThread qui crée et démarre 4 threads
qui affichent les nombres de 0 à 5 000 (sans numéro unique par thread donc).
-
Exécutez le programme plusieurs fois, que remarque t'on ?
Puis, en regardant l'affichage (scroller au besoin), qu'y-a-t'il de bizarre ?
Est-ce que tout ceci est bien normal ?
-
Modifiez votre code pour afficher en plus le numéro de chaque thread.
Rappel de Java:
- Il est possible d'utiliser à l'intérieur d'une lambda des variables
déclarées à l'extérieur que si leur valeur ne change pas.
Exercice 2 - This is the end, my friend ...
On souhaite afficher le message "le programme est fini",
lorsque toutes les threads ont fini de faire leurs calculs.
-
Recopiez le programme de l'exercice précédent dans une nouvelle classe
HelloThreadJoin puis modifiez le pour que soit affiché le message "le programme est fini"
lorsque toutesles threads ont fini leurs calculs.
Si vous cherchez comment attendre que des threads aient fini
d'exécuter leur Runnable, la méthode que vous cherchez est
Thread.join.
Runnable r = () -> {
...
};
Thread t = new Thread(r);
t.start();
t.join();
System.out.println("La thread t a fini son Runnable");
Exercice 3 - When things add up
On souhaite modifier le programme précédent pour qu'au lieu d'afficher les nombres,
on les stocke dans une unique ArrayList (une seule liste pour toutes
les threads) dont on affichera la taille à la fin du programme.
-
Recopiez la classe HelloThreadJoin dans une nouvelle classe
HelloListBug puis modifiez la pour ajouter les nombres au lieu de les afficher et pour afficher la taille finale
une fois toutes les threads terminées.
Exécuter le programme plusieurs fois et noter les différents affichages (oui, même les exceptions).
-
Expliquer quel est le problème lorsqu'une exception est levée. Pour comprendre, il faut regarder le code de la méthode ArrayList.add.
-
Puisque l'exception se produit lorsque l'on agrandit l'ArrayList, on peut essayer de la créer avec la bonne taille.
ArrayList list = new ArrayList(5_000*4);
Exécuter le programme plusieurs fois et noter les différents affichages.
Expliquer quel est le problème.
-
Corriger le problème et vérifier que la correction que vous avez effectuée, exécute bien les threads
en parallèle et non pas les unes derrière les autres.
Exercice 4 - Coitus interruptus
On souhaite avoir 4 threads qui affichent chacune leur numéro et un compteur indéfiniment
(chaque thread a son propre compteur). Pour éviter de faire chauffer la machine,
l'affichage se fera une fois par seconde (en utilisant
Thread.sleep()).
De plus, la thread
main va lire des entiers sur l'entrée standard
et si l'utilisateur entre une valeur correspondant au numéro d'une thread,
cette dernière sera arrêtée.
Le code pour lire sur l'entrée standard est le suivant:
System.out.println("enter a thread id:");
try(Scanner scanner = new Scanner(System.in)) {
while(scanner.hasNextInt()) {
int threadId = scanner.nextInt();
...
}
}
Note: dans les vrais programmes, on utilise rarement le
Scanner car il est très lent
(comme le
scanf en C), on utilise plutôt un
BufferedReader ou
Files.lines.
Rappel: on utilise Ctrl-D (Ctrl-Z sous Microsoft Windows) pour indiquer au terminal
qu'il faut fermer l'entrée standard.
-
Pourquoi n'est il pas possible d'arréter une thread de façon non coopérative ?
-
Expliquer comment utiliser les méthodes thread.interrupt et
Thread.interrupted (noter que la seconde est statique et pas la première)
pour arrêter des threads dans le cas où il n'y a pas d'opération bloquante.
-
Et si il y a une opération bloquante ?
-
Que se passe-t-il lorsque l'on appelle Thread.currentThread().interrupt() ?
-
Expliquer la trop subtile différence entre les méthodes Thread.interrupted
et thread.isInterrupted de la classe Thread.
Pourquoi dit-on que la méthode Thread.interrupted est mal nommée ?
-
Ecrire le code.
-
Comment faire pour que le programme se termine si l'on fait un Ctrl-D dans le terminal ?
© Université de Marne-la-Vallée