:: Enseignements :: ESIPE :: E4INFO :: 2014-2015 :: Java Réseau I - Concurrence et E/S ::
[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écuterons 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 responsable respectivement de mettre une valeur dans la queue et de retirer une valeur de celle-ci ?
  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 affiche 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 les deux threads au lieu d'afficher les messages sur la console, les inséres 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.
    Faite 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 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. Modifier 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. Modifier 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.