Examen 2h sur machine


L'examen est composé de 3 exercices indépendants qui peuvent être traités dans l'ordre que vous voulez.

Rappel : vous devez configurer le workspace d'Eclipse (File > Switch WorkSpace) pour qu'il corresponde au répertoire EXAM présent dans le home de votre session de TP noté.

Vérifier que tous vos fichiers sont bien dans le répertoire EXAM. Tout ce qui n'est pas dans ce répertoire est perdu quand vous vous déconnectez.

La javadoc 19 est là : https://igm.univ-mlv.fr/~juge/javadoc-19/.

Vous avez le droit de consulter les transparents du cours pendant l'examen.

Santa's Sack

Dans cet exercice, on se propose de créer une classe représentant la hotte de Père Noël (Sack). Pour simplifier, on ne mettra dans la hotte que le poids des cadeaux en kilogrammes donc des int. À la création de la hotte, on donnera le poids maximal que la hotte peut porter. Comme toutes les hottes dignes de ce nom, notre hotte devra être thread-safe.

La classe Sack aura les méthodes suivantes :

Codez la classe thread-safe Sack décrite précédemment en utilisant des ReentrantLock.

On veut maintenant rajouter une méthode List<Integer> takeGiftsUntil(int weight) qui va prendre (donc retirer) des cadeaux dans la hotte en commençant toujours par le plus récemment ajouté jusqu'à avoir pris au moins weight kilogrammes de cadeaux. Dès que le poids est atteint ou dépassé, la méthode renvoie la liste des poids des cadeaux retirés. La méthode prend les cadeaux dès qu'elle le peut et attend d'avoir au moins le poids total demandé. On pourra ainsi demander 1000 kg de cadeaux dans une hotte de 500 kg. Autrement dit, la méthode prend des cadeaux puis, si nécessaire, attend que de nouveaux cadeaux soient rajoutés pour continuer.

On veut aussi rajouter une méthode int weightNeeded() qui renvoie la somme des poids encore nécessaires pour satisfaire tous les threads qui sont en train d'exécuter la méthode takeGiftsUntil.

Rajoutez les deux méthodes demandées à votre classe Sack.

On veut maintenant spécifier le comportement de nos méthodes en cas d'interruption.

Si les méthodes putGift et takeGift sont interrompues, elles lèvent une InterruptedException.

Si la méthode takeGiftsUntil est interrompue, elle ne s'arrête pas, mais elle devient prioritaire pour retirer des cadeaux. Tant qu'elle n'a pas fini, aucun autre thread ne peut retirer de cadeau : si un thread est en train d'appeler une des méthodes takeGiftsUntil ou takeGifts, ces méthodes sont bloquées en attendant que cette méthode soit terminée). Si d'autres threads ont été interrompus pendant qu'ils appelaient la méthode takeGiftsUntil, ils sont eux aussi prioritaires et peuvent continuer à enlever des paquets. Pour signaler que le thread a été interrompu, la méthode takeGiftsUntil positionnera le statut d'interruption avant de renvoyer la liste des poids des cadeaux.

Copiez votre classe Sack dans une classe SackWithInterruption est implanter la gestion des interruptions demandée.

PokemonFactory

Dans cet exercice, on vous fournit une petite API factice qui permet d'attraper des Pokemon, de les mettre dans des Pokeball et de mettre plusieurs Pokeball dans une boîte (Crate). Le code de l'API est dans PokeAPI.java. Vous n'avez pas besoin de lire le code de l'API, toutes les informations nécessaires sont disponibles dans la brève description ci-dessous.

Un Pokemon possède un nom (name) et une rareté (rarity) comprise entre 0 et 5.

public record Pokemon(String name, int rarity){..}    

La méthode static Pokemon capture() permet d'attraper un Pokemon.

Une Pokeball possède un Pokemon pokemon et une valeur (value) entre 0 et 10 inclus.

public record Pokeball(Pokemon pokemon, int value){..}

La méthode static Pokeball trap(Pokemon pokemon) permet de mettre un Pokemon dans une Pokeball.

Une Crate contient au plus 5 Pokeball qui ont toutes la même valeur. Elle est crée grâce à la méthode static Crate box(List<Pokeball> pokeballs).

Le code ci-dessous donne un exemple d'utilisation de l'API.

 public static void main(String[] args) throws InterruptedException {
        var pokemon = PokeAPI.capture();
        System.out.println(pokemon); // Pokemon[name=Ronflex, rarity=1]
        var pokeball = PokeAPI.trap(pokemon); 
        System.out.println(pokeball); // Pokeball[pokemon=Pokemon[name=Ronflex, rarity=1], value=2]
        var crate = PokeAPI.box(List.of(pokeball));
        System.out.println(crate); // Crate[content=[Pokeball[pokemon=Pokemon[name=Ronflex, rarity=1], value=2]]]
    }    

Dans cet exercice, on vous demande dans le main d'une classe PokemonFactory de :

Écrivez la classe PokeFactory demandée.

On veut maintenant que, lorsque que l'on a réussit à produire la première Crate de Pokeball de valeur 20, le programme s'arrête. On demande que les threads qui produisent les Crate produisent une dernière Crate, même incomplète, et l'affiche avant de s'arrêter.

Copiez votre code dans une classe PokeFactoryStop et modifier le main pour obtenir le comportement demandé.

MaxRecorder en lock-free

Dans cet exercice, on cherche à créer une classe MaxRecorder thread-safe que l'on crée avec une certaine capacité N. Cette classe possède une méthode process qui prend en paramètre un entier positif et qui renvoie vrai si l'entier proposé fait partie des N plus grands nombres qui ont été proposés lors d'appels à la méthode process depuis la création de la classe.

var recorder = new MaxRecorder(2);
recorder.process(1); // => true   
recorder.process(2); // => true
recorder.process(0); // => false
recorder.process(3); // => true
recorder.process(1); // => false
recorder.process(2); // => false // euh ?
recorder.process(3); // => true

Donnez une implémentation dans le cas de la capacité 1 dans une classe MaxRecorderOne qui n'utilise ni section critique, ni verrou, en utilisant la classe VarHandle.