TP Java Avancé 10/03/2004 -- Ing2 SIGL1 -- Exercice =================================================== I. Modalités de rendu --------------------- - Date/heure : mardi 17/03/2004 à 14:00 - Répertoire : ~/rendu/java/sigl1/threads2 - Fichiers : FactoryFrame.java, FactoryStock.java, Producer.java, Consumer.java (*) - Droits : 700 répertoires, 600 fichiers (*) Gardez la clause package (org.insia.thread) mais ne me rendez que le fichier, sans le placer dans un sous-répertoire correspondant. Juste à même le répertoire de rendu. Evidemment, ne TRAVAILLEZ PAS dans votre répertoire de RENDU. ------------------------------------------------------------------------------ Principe ------------------------------------------------------------------------------ Le but de l'exercice est de simuler le comportement d'une usine : des producteurs et des consommateurs vont utiliser un même stock de produits, soit pour en ajouter, soit pour en retirer. Vous réaliserez une petite interface graphique pour vous permettre d'ajouter des producteurs et des consommateurs, et pouvoir visualiser en temps réel le niveau du stock de produits de l'usine. Pour cela, vous aurez à réaliser 4 classes : - FactoryFrame : la partie graphique de l'exercice. - FactoryStock : le stock de produits de l'usine. - Producer : un producteur de produits. - Consumer : un consommateur de produits. ------------------------------------------------------------------------------ La classe FactoryFrame ------------------------------------------------------------------------------ Vous devez réaliser une classe FactoryFrame qui hérite de JFrame et possède : - sur une première ligne un label indiquant le nombre de producteurs ainsi qu'un bouton pour en ajouter. - sur une seconde ligne un label indiquant le nombre de consommateurs ainsi qu'un bouton pour en ajouter. - sur une dernière ligne une JProgressBar qui indique le pourcentage de remplissage de l'entrepôt de l'usine. Le seul constructeur autorisé est : public FactoryFrame(final int capacity) qui prend en paramètre la capacité maximale de stockage de l'usine. La classe a une méthode main qui crée le frame et l'affiche. Votre frame DOIT, à la fermeture, terminer la JVM (setDefaultCloseOperation). La capacité est fournie en ligne de commande au main, sous forme d'un entier décimal. Consignes : - la fenêtre mesure 300 x 180 pixels et est titrée "Factory Demo". - tous les composants sont situés à 20 px des bords de la fenêtre. - au lancement de l'application, il n'existe aucun producteur ni aucun consommateur. - on distingue le singulier du pluriel dans les labels. - les boutons possèdent respectivement les mnémoniques Alt+P et Alt+C, ont une taille de 150 x 25 et n'ajoutent qu'un utilisateur par clic (producteur ou consommateur, respectivement). - la barre de progression est mise à jour toutes les 100 ms, pour cela vous pouvez utiliser la classe javax.swing.Timer qui permet d'exécuter répétitivement une action à intervalle de temps régulier (scheduler). N'oubliez pas qu'une fois créé, il faut le lancer via sa méthode start(). Vous disposez d'une capture d'écran D'EXEMPLE sur : http://profs.insia.org/~tdd/sigl1/java/tp/threads2/factory_demo.png ------------------------------------------------------------------------------ La classe FactoryStock ------------------------------------------------------------------------------ La classe FactoryStock représente le stock de l'usine. On souhaite que ce stock ait le comportement d'une "file". Une file est une liste où les éléments sont ajoutés toujours du même côté, et retirés toujours de l'autre (first-in-first-out). Pour cela vous utiliserez une LinkedList de manière interne (attention, la javadoc spécifie bien que LinkedList est une implémentation non synchronisée de l'interface List). Le seul constructeur autorisé est : public FactoryStock(final int capacity) qui prend en paramètre la capacité maximale de stockage. Si une valeur négative ou nulle est passée en paramètre, vous devez lever une IllegalArgumentException avec un message idoine. Les méthodes à implémenter sont : - public int getSize() retourne le nombre de produits en stock. - public int getCapacity() retourne la capacité maximale de stockage. - public boolean isEmpty() retourne true ssi aucun produit n'est en stock ; false autrement. - public boolean isFull() retourne true ssi le nombre de produit en stock égale la capacité maximale de stockage ; false autrement. - public Object getProduct() throws InterruptedException retourne le produit qui a été ajouté le premier parmi ceux en stock. Cette méthode ne renvoie jamais null : si aucun produit n'est disponible, la méthode va attendre qu'un produit devienne disponible et le renvoyer. - public void putProduct(final Object object) throws InterruptedException ajoute en queue le produit passé en paramètre. Si le stock est plein, la méthode attend qu'un consommateur retire un produit pour enfin pouvoir ajouter le produit passé en queue. ------------------------------------------------------------------------------ La classe Producer ------------------------------------------------------------------------------ La classe Producer implémente l'interface Runnable. Le seul constructeur autorisé prend une instance de FactoryStock en paramètre. Vous devez implémenter la méthode run() : - un producteur produira en boucle des produits qui seront ajoutés au stock spécifié tant qu'aucun autre thread ne cherchera à l'interrompre. - il crée un produit à la fois : une instance d'Integer dont la valeur X est aléatoirement générée entre 0 et 100. Il met d'ailleurs X ms à produire cet objet. Utilisez java.util.Random et sa méthode nextInt(int) pour obtenir une génération aussi "aléatoire" que possible et non "cassée" par des modulos ou des troncatures... - une fois l'objet créé, il le dépose dans le stock. ------------------------------------------------------------------------------ La classe Consumer ------------------------------------------------------------------------------ La classe Consumer implémente l'interface Runnable. Le seul constructeur autorisé prend une instance de FactoryStock en paramètre. Vous devez implémenter la méthode run() : - un consommateur consommera en boucle les produits du stock tant qu'aucun autre thread ne cherchera à l'interrompre. - il consomme un produit à la fois, qu'il retire du stock. Il met X ms à consommer cet objet (X la valeur int de l'objet Integer retiré du stock). ------------------------------------------------------------------------------ Ressources ------------------------------------------------------------------------------ http://profs.insia.org/~tdd/sigl1/java/ http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html Javadoc... Norme INSIA... Cerveau... -- FIN DE SUPPORT TP --