:: Enseignements :: Master :: M1 :: 2014-2015 :: 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 peu changer) qui exécute un même
code afffichant les nombre 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 affiche les nombres de 0 à 5000 (sans numéro unique par thread donc).
-
Exécuter 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 tous ceci est bien normal ?
-
Modifier votre code pour afficher en plus le numéro de chaque thread.
Rappel de Java:
- Il n'est possible d'utiliser à l'intérieur d'une lambda des variables
déclarées à l'extérieur que si la valeur de la variable ne change pas.
Exercice 2 - This is the end, my friend ...
On souhaite afficher 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 sous un nouveau nom de 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 on fait pour attendre que des threads aient fini
d'exécuter leurs 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 stocke ceux-ci 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 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 vous faut regarder le code de la méthode ArrayList.add.
-
Puisque l'exception se produit lorsque l'on agrandit la ArrayList, on peut essayer de créer la ArrayList 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,
celle-ci va arrêter la thread correspondante.
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 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 appel Thread.currentThread().interrupt() ?
-
Expliquer la trop subtile différences 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