:: Enseignements :: Master :: M1 :: 2015-2016 :: Java Avancé ::
[LOGO]

Producteur / consommateur


Exercice 1 - Producer / Consumer

Nous cherchons dans cet exercice à simuler un environement avec plusieurs producteurs et plusieurs consommateurs. Pour cela, nous utiliserons des threads qui exécuteront périodiquement soit un code qui produit des valeurs soit un code qui consomme ces valeurs.

  1. Rappeler quel problème résoud le design pattern Producer/Consumer et comment il fonctionne ?
  2. L'interface d'un buffer utilisé pour un producteur / consommateur est nommée java.util.concurrent.BlockingQueue en Java.
    Comment s'appellent les méthodes de l'interface BlockingQueue qui permettent, respectivement, de mettre une valeur dans la queue et d'en retirer une valeur ?
  3. Ecrire dans un main une thread qui affiche périodiquement (disons toutes les 1 ms) le texte "hello" sur la console.
    Modifier votre code pour avoir deux threads qui affichent périodiquement "hello 0" ou "hello 1" (hello suivi d'un numéro de thread) respectivement toutes les 1 ms et toutes les 4 ms.
    Note: pas de copier/coller SVP !
  4. Modifier une nouvelle fois le code pour que, au lieu d'afficher les messages sur la console, les deux threads les insèrent dans une BlockingQueue.
    Que se passe t'il si l'implantation de BlockingQueue est une LinkedBlockingQueue ?
    Même question si l'implantation est une ArrayBlockingQueue.
    Que peut-on en conclure ?
  5. Ecrire un nouveau code qui permet de retirer les messages de la BlockingQueue et de les afficher sur la console. Créer 3 threads exécutant le code respectivement toutes les 2 ms, 3 ms et 5 ms.
    Faites varier le nombre de threads et les temps pour voir ce qu'il se passe.

Exercice 2 - Queue bloquante

Nous allons maintenant ré-implanter (en partie) une queue bloquante bornée utilisant un tableau circulaire avec ses deux opérations put et take.
Note: la classe java.util.ArrayDeque implante déjà un buffer circulaire non thread-safe.

  1. Ecrire une classe SynchronizedBlockingBuffer utilisant des blocs synchronized qui dans un premier temps, lève une exception
    • dans put si il n'y plus de place (la queue est pleine).
    • dans take si il n'y a pas d'élement (la queue est vide).
    et possède une taille (strictement positive) donnée à la construction.
    Pour tester, vous pourrez ré-utiliser le code du premier exercice.
  2. Modifiez votre code pour que la méthode put soit bloquante si la queue est pleine.
    Attention, penser à reveiller la thread lorsque la queue n'est plus pleine.
  3. Modifiez votre code pour que la méthode take soit bloquante si la queue est vide.
  4. Ecrire une nouvelle classe LockedBlockingBuffer qui utilise les verrous ré-entrant du package java.util.concurrent.locks.Lock.