Dans cet exercice, on cherche à comprendre le fonctionnement des interruptions.
Pourquoi n'est il pas possible d’arrêter un thread de façon non coopérative ?
Rappeler ce qu'est un appel de méthode bloquant.
À quoi sert la méthode d'instance interrupt()
de la classe Thread
?
Expliquer comment interrompre un thread en train d'effectuer un appel de méthode bloquant et le faire sur l'exemple suivant : le thread main
attend 5 secondes avant d'interrompre le thread qui dort et ce dernier affiche son nom.
public static void main(String[] args) { Thread.ofPlatform().start(() -> { for (var i = 1;; i++) { try { Thread.sleep(1_000); System.out.println("Thread slept " + i + " seconds."); } catch (InterruptedException e) { // TODO } } }); }
Expliquer, sur l'exemple suivant, comment utiliser la méthode
Thread.interrupted
pour arrêter le calcul de findPrime()
qui n'est pas une méthode bloquante. Modifier le code de findPrime
(mais ni sa signature, ni isPrime
) pour pouvoir l'interrompre. Dans ce cas, elle renvoie un OptionalLong
vide.
Puis faire en sorte que le main
attende 3 secondes avant d'interrompre le thread qui cherche un nombre premier, en affichant "STOP".
public static boolean isPrime(long candidate) { if (candidate <= 1) { return false; } for (var i = 2L; i <= Math.sqrt(candidate); i++) { if (candidate % i == 0) { return false; } } return true; } public static OptionalLong findPrime() { var generator = ThreadLocalRandom.current(); for (;;) { var candidate = generator.nextLong(); if (isPrime(candidate)) { return OptionalLong.of(candidate); } } } public static void main(String[] args) { Thread.ofPlatform().start(() -> { System.out.println("Found a random prime : " + findPrime().orElseThrow()); }); }
Expliquer la (trop) subtile différence entre les méthodes Thread.interrupted
et thread.isInterrupted
de la classe Thread
.
On souhaite maintenant faire en sorte que findPrime
s'arrête dès que possible si le thread qui l’utilise est interrompu. Pour cela, modifier le code de findPrime
et/ou isPrime
sans modifier leur signature.
Remarque : il est possible pour un thread de demander à s'interrompre lui même ainsi : Thread.currentThread().interrupt();
Et si vous pouvez modifier le code des méthodes ET leur signature, que faites-vous ?
Pouvez-vous garantir que le programme afichera soit un nombre, soit "STOP", mais pas les deux ?
On souhaite avoir 4 threads qui affichent chacun 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, le thread main
va lire des entiers sur l'entrée standard
et si l'utilisateur entre une valeur correspondant au numéro d'un thread,
ce dernier sera arrêté.
Le code pour lire sur l'entrée standard est le suivant :
System.out.println("enter a thread id:"); try (var input = new InputStreamReader(System.in); var reader = new BufferedReader(input)) { String line; while ((line = reader.readLine()) != null) { var threadId = Integer.parseInt(line); ... } }Rappel : on utilise Ctrl-D (Ctrl-Z sous Microsoft Windows) pour indiquer au terminal qu'il faut fermer l'entrée standard.
Comment faire pour que le programme se termine si l'on fait un Ctrl-D
dans le terminal ?
"Le Juste Prix", The price is right en anglais, est un jeu télévisé ou plusieurs candidats s'affrontent pour gagner un article (dont le prix n'est pas connu par les candidats). Chaque candidat propose un prix et le candidat qui indique le prix le plus proche du prix réel d'un article gagne cet article.
Dans cet exercice, vous devez implanter la même mécanique de jeu avec un thread simulant un candidat.
Les tests JUnit pour toutes les questions de l'exercice sont dans la classe
ThePriceIsRightTest.java.
Attention, les tests sont volontairement simples pour que vous puissiez les lires.
Ils peuvent reporter des erreurs sur la console au lieu de reporter les erreurs dans la partie graphique.
Donc un test passe s'il est vert et qu'il ne fait pas d'erreur sur la console.
ThePriceIsRight
est initialisé avec le prix réel de l'article, ainsi que le nombre de candidats.
var thePriceIsRight = new ThePriceIsRight(100, 2);
propose
prend en paramètre un entier qui correspond au prix proposé par un candidat (un thread). Cette méthode bloque tant que tous les candidats n'ont pas soumis leur prix puis elle renvoie true
au thread qui a proposé le prix le plus proche et false
à tous les autres threads.
propose
,
la proposition de prix des threads supplémentaires ne sera pas prise en compte et la méthode propose
renvoie false
.
propose
renvoie false
.
false
.
private int distance(int price) { return Math.abs(price - realPrice); }
Stream
, vous pouvez utiliser le collector Collectors.minBy
,
mais vous pouvez aussi écrire le code à la main, pourvu que ce soit correct.
Écrire le code de la classe ThePriceIsRight
.