10 Commits

Author SHA1 Message Date
Rochas
ecc722b868 ajout de couleur dans la console (oui je m'amuse sur un tp déjà rendu) 2024-12-20 00:25:45 +01:00
Rochas
bac0dc7d1a rapport 2024-12-09 22:23:44 +01:00
Rochas
c5e73329b6 sémaphore sur les compatiments 2024-12-09 22:15:57 +01:00
Rochas
06bf38a576 rapport 2024-12-09 19:59:53 +01:00
Rochas
43de4fad01 rapport 2024-12-09 19:57:09 +01:00
Rochas
3ec65a8a29 rapport 2024-12-09 19:00:42 +01:00
Rochas
ac9bb3129b correction Employe du buffet + Stand de cuisson refait avec un notify et wait 2024-12-09 18:57:40 +01:00
Rochas Thibaut
efacbbd377 Update rapport.txt 2024-12-09 16:13:31 +00:00
trochas
e3dc8dfe9a rapport pour sémaphore 2024-12-08 13:40:51 +01:00
trochas
c92ba8c0f4 le Client utilise un sméaphore pour cuir son plat 2024-12-08 13:38:07 +01:00
9 changed files with 222 additions and 137 deletions

BIN
lib/jansi-2.4.0.jar Normal file

Binary file not shown.

View File

@@ -1,32 +1,45 @@
Thibaut ROCHAS
Tuan Minh VU
Difficulté :
On avait commencé dans Stand_de_cuisson par faire une Queue, on a ensuite
décidé de simplement synchroniser le stand de cuisson et le client, qui est au
final beaucoup plus simple, mais le verrou n'est plus équitable, ce n'est plus le
Client qui attend depuis le plus long temps qui est prioritaire.
Pour les compartiments, nous n'avons pas commencé par faire avec un sémaphore mais
nous nous sommes rendus compte que ça pouvait entraîner des problèmes de
synchronisation (par exemple en forçant les client a vider les compartiment)
Explication code :
Nous avons la Class Au_Wok qui contient le main(), on y initialise les clients Nous avons la Class Au_Wok qui contient le main(), on y initialise les clients
ainsi que le restaurant, puis on start tous les clients. ainsi que le restaurant, puis on start tous les clients.
Le constructeur Restaurant initialise le Buffet, un tableau de 4 Compartiment Le constructeur Restaurant initialise le Buffet : le Buffet qui initialise dans
(poisson, viande, légume et nouille), le stand de cuisson, l'Employe_du_buffet son constructeur les 4 Compartiment (poisson, viande, légume et nouille), le
et le Cuisinier. Il star en suite start ces deux derniers. stand de cuisson, le Cuisinier, l'Employe_du_buffet. Puis il peut star l'employé
du buffet et le Cuisinier.
Le run de Client va suivre ces étapes : Le run de Client va suivre ces étapes :
(1) Entrer dans le restaurant en vérifiant bien que le restaurant est libre (1) Entrer dans le restaurant en vérifiant bien que le restaurant est libre
(2) Prendre une portion de chaque Compartiment du buffet, en vérifiant (2) Prendre une portion de chaque Compartiment du buffet, en vérifiant que
le verrou du compartiment est libre avant de lui-même le verrouiller, après le sémaphore du compartiment est libre avant de lui-même le verrouiller,
c'être servi il déverrouille fait un notifyAll pour réveiller les clients après s'être servi il libère le sémaphore.
ou l'employer du buffet qui pourrait attendre. Et fais aussi un notify sur le buffet pour que l'employé du buffet
(3) Cuire au stand, en se mettant dans la queue (il notifyAll le stand pour puisse refaire un tour des compartiments.
réveiller le cuisinier), quand son plat est cuit le cuisinier le sort de la (3) Cuire au stand, il "fait la queue" en attendant que la palce se libère,
queue (le stand fait un notifyAll pour réveiller le client) il wait sur le stand de cuisson en attendant d'être notify.
(4) Manger (4) Manger
(5) Sort, en faisant un notifyAll sur le restaurant pour prévenir tout autre (5) Sort, en faisant un notifyAll sur le restaurant pour prévenir tout autre
thread client attendant pour entrer thread client attendant pour entrer
Le run du cuisinier, fait une boucle pour vérifier si un client est présent en L'employé du buffet fait le tour de chaque Compartiment du Buffet, s'il y a un
tête de la queue du stand de cuisson. Si oui, alors il fait cuire son plat. un compartiment à moins de 100g alors il vérifie qu'il est libre (sémaphore) et
Une fois fini, il sort le client le la queue et fait faire un notifyAll au stand le remplit. Après avoir fait un tour il fait sleep sur le buffet, le buffet le
pour prévenir le client que son plat est fini. réveillera à chaque fois qu'un client se soit servi.
L'employer du buffet fait le tour de chaque compartiment du buffet, s'il y a un Le Cusinier attend qu'il y est un client, si non il dors en écoutant le stand de
un buffet à moins de 100g alors il vérifie qu'il est libre (se met en wait sinon) cuisson. Quand un client est là il fait cuir son plat puis notifyAll pour pévenir
et le remplit. à la fois le cient qui faisait cuir son plat et tout les client en attente.
Difficulté :
Nous avons pas vraiment rencontré de difficulté, on a juste eu parfois quelque
oublie (notifyAll manquant par exemple)

32
src/Buffet.java Normal file
View File

@@ -0,0 +1,32 @@
public class Buffet {
private Compartiment compartiment[];
Buffet(){
compartiment = new Compartiment[4];
this.compartiment[0] = new Compartiment("poisson");
this.compartiment[1] = new Compartiment("viande");
this.compartiment[2] = new Compartiment("légume");
this.compartiment[3] = new Compartiment("nouille");
}
public Compartiment getCompartiment(int i){
return compartiment[i];
}
public int length(){
return compartiment.length;
}
/*
* return true si un des compartiment n'est pas sufisament remplis
*/
public boolean isEmpty(){
boolean b = false;
for(int i = 0; i <compartiment.length; i++){
b= b||(compartiment[i].getQuantite()<100);
}
return b;
}
}

View File

@@ -1,4 +1,5 @@
import java.util.Random; import java.util.Random;
import static org.fusesource.jansi.Ansi.*;
public class Client extends Thread { public class Client extends Thread {
private int MAX_PORTION = 100; private int MAX_PORTION = 100;
@@ -13,8 +14,8 @@ public class Client extends Thread {
public void run(){ public void run(){
try{ try{
entrer(); entrer();
for(int i = 0; i<this.restaurant.buffet.length; i++){ for(int i = 0; i<this.restaurant.buffet.length(); i++){
prendre_portion(this.restaurant.buffet[i]); prendre_portion(i);
} }
cuir_au_stand(restaurant.stand_de_cuisson); cuir_au_stand(restaurant.stand_de_cuisson);
manger(); manger();
@@ -24,45 +25,68 @@ public class Client extends Thread {
} }
} }
public void prendre_portion(Compartiment compartiment){ /*
synchronized(compartiment){ * Prendre une portion du compartiment i du buffet
int r =new Random().nextInt(MAX_PORTION); * Le client attent que le compartiment soit libre avant de se servir avec un sémaphore.
* Une fois libre il se sers pendant 200 à 300ms
* Il libère le sémaphore et norify avec le buffet pour que l'employer buffet reférifit le buffet
*/
public void prendre_portion(int i){
Compartiment compartiment = this.restaurant.buffet.getCompartiment(i);
Boolean servi = false;
int r =new Random().nextInt(MAX_PORTION);
while(!servi){
try{ try{
while(r > compartiment.getQuantite() || !compartiment.isLibre()){ compartiment.getSemaphore().acquire();
compartiment.wait(); if(r<=compartiment.getQuantite()){
compartiment.servir(r);
try{
long temps_servir =new Random().nextInt(300 - 200) + 200;
Thread.sleep(temps_servir);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(this.getNameClient() + " : a pris une portion de " + compartiment.getName() + " " + r);
servi = true;
} }
} catch (InterruptedException e){ }catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally{
compartiment.getSemaphore().release();
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
} }
compartiment.setLibre(false); }
compartiment.servir(r); synchronized(this.restaurant.buffet){
try{ this.restaurant.buffet.notify();
long temps_servir =new Random().nextInt(300 - 200) + 200;
Thread.sleep(temps_servir);
}catch(InterruptedException e){
e.printStackTrace();
}
compartiment.setLibre(true);
System.out.println(this.getNameClient() + " : a pris une portion de " + compartiment.getName());
compartiment.notifyAll();
} }
} }
/*
* essaye d'entrer dans le restaurant
* si il n'est pas libre il wait et attend qu'un client sorte
*/
public void entrer(){ public void entrer(){
synchronized(restaurant){ synchronized(restaurant){
try{ try{
while(!restaurant.libre()){ while(!restaurant.libre()){
restaurant.wait(); restaurant.wait();
} }
System.out.println("+ " + this.getNameClient() + " : est entré dans le restaurant"); System.out.println( ansi().fgGreen().a("+ ").reset().a(this.getNameClient() + " : est entré dans le restaurant"));
//System.out.println("+ " + this.getNameClient() + " : est entré dans le restaurant");
restaurant.ajouterClient(); restaurant.ajouterClient();
}catch (InterruptedException e) { }catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }
/*
* le Thread s'endort pendant 1 à 2 s le temps de manger
*/
public void manger(){ public void manger(){
try{ try{
System.out.println(this.getNameClient() + " : mange"); System.out.println(this.getNameClient() + " : mange");
@@ -73,30 +97,45 @@ public class Client extends Thread {
} }
} }
/*
* le client sort, et fait un notify() sur le restaurant
* (tout les Thread en attente sur le restaurant sont des clients en attente pour entrer
* et qu'un seul client en attente poura entrer, donc ça ne sers à rien de faire un notifyAll)
*/
public void sort(){ public void sort(){
synchronized(restaurant){ synchronized(restaurant){
System.out.println("- " + this.getNameClient() + " : sorti");
System.out.println( ansi().fgRgb(255,0,0).a("- ").reset().a(this.getNameClient() + " : est sorti dans le restaurant"));
//System.out.println("- " + this.getNameClient() + " : sorti");
restaurant.diminuerClient(); restaurant.diminuerClient();
restaurant.notifyAll(); restaurant.notify();
} }
} }
/*
* faire cuir le plat
* wait en attendant que la place se libère
* une fois la place prise on wait sur le stand et on laisse faire le stand et le cuisinier
*/
public void cuir_au_stand(Stand_de_cuisson stand){ public void cuir_au_stand(Stand_de_cuisson stand){
stand.ajouter_client(this);
System.out.println(this.getNameClient() + " : attend pour faire cuir son plat"); System.out.println(this.getNameClient() + " : attend pour faire cuir son plat");
synchronized(stand){ synchronized(stand){
try{ try{
while(stand.containsClient(this)){ while(stand.getClient()!=null){
stand.wait(); stand.wait();
} }
}catch (InterruptedException e){ stand.faire_cuire(this);
e.printStackTrace(); while(stand.getClient()==this){
stand.wait();
}
}catch (InterruptedException e) {
e.printStackTrace();
} }
} }
System.out.println(this.getNameClient() + " : le plat est cuit"); System.out.println(this.getNameClient() + " : le plat est cuit");
} }
public String getNameClient(){ public String getNameClient(){
return ("Client " + this.id); return ("Client " + this.id);
} }

View File

@@ -1,13 +1,15 @@
import java.util.concurrent.Semaphore;
public class Compartiment{ public class Compartiment{
protected final int QUANTITE_MAX = 1000; protected final int QUANTITE_MAX = 1000;
private int quantite_courant; private int quantite_courant;
private String name; private String name;
private boolean libre; private Semaphore semaphore;
Compartiment(String name){ Compartiment(String name){
this.quantite_courant = 500; this.quantite_courant = 200;
this.name = name; this.name = name;
this.libre = true; this.semaphore=new Semaphore(1);
} }
synchronized void remplir(){ synchronized void remplir(){
@@ -27,11 +29,7 @@ public class Compartiment{
return this.name; return this.name;
} }
synchronized boolean isLibre(){ public Semaphore getSemaphore() {
return this.libre; return semaphore;
}
synchronized void setLibre(boolean libre){
this.libre = libre;
} }
} }

View File

@@ -1,45 +1,53 @@
import java.util.Random; import java.util.Random;
import static org.fusesource.jansi.Ansi.*;
public class Cuisinier extends Thread { public class Cuisinier extends Thread {
private Stand_de_cuisson stand; Stand_de_cuisson stand;
public Cuisinier(Stand_de_cuisson stand_de_cuisson){ public Cuisinier(Stand_de_cuisson stand){
this.stand= stand_de_cuisson;
this.setDaemon(true); this.setDaemon(true);
this.stand = stand;
} }
/*
* regarde si un client est au stand, si non il s'endort
* si un client est au stand, il fait cuire son plat
*/
public void run(){ public void run(){
while(Thread.currentThread().isDaemon()){
attendreClient();
}
}
private void attendreClient(){
Client client = stand.getClient();
synchronized(stand){ synchronized(stand){
try{ while(Thread.currentThread().isDaemon()){
while(client==null){ Client client = stand.getClient();
stand.wait(); if(client!=null){
client= stand.getClient(); faire_cuire(client);
}
else{
try {
stand.wait();
} catch (Exception e) {
e.printStackTrace();
}
} }
} }
catch(InterruptedException e){
e.printStackTrace();
}
} }
faire_cuire(client);
} }
/*
* fait cuir le plat du client pendant 200 à 400ms
* une fois fini il indique au stand que la cuisson est fini (qui fait notifyAll aux clients)
*/
public void faire_cuire(Client client){ public void faire_cuire(Client client){
System.out.println("# Cuisinier : fait cuire le plat de " + client.getNameClient()) ; System.out.println( ansi().fgRed().a("Cuisinier").reset().a(": fait cuire le plat de " + client.getNameClient()));
//System.out.println("# Cuisinier : fait cuire le plat de " + client.getNameClient()) ;
try{ try{
long temps_cuire =new Random().nextInt(300 - 100) + 100; long temps_cuire =new Random().nextInt(400 - 200) + 200;
Thread.sleep(temps_cuire); Thread.sleep(temps_cuire);
}catch(InterruptedException e){ }catch(InterruptedException e){
e.printStackTrace(); e.printStackTrace();
} }
System.out.println("# Cuisinier : a fini de cuire le plat de " + client.getNameClient()) ; System.out.println( ansi().fgRed().a("Cuisinier").reset().a(": a fini de cuire le plat de " + client.getNameClient()));
stand.nextClient();
stand.finir_cuit(); //System.out.println("# Cuisinier : a fini de cuire le plat de " + client.getNameClient()) ;
stand.cuissonFini();
} }
} }

View File

@@ -1,27 +1,48 @@
import static org.fusesource.jansi.Ansi.*;
public class Employe_du_buffet extends Thread{ public class Employe_du_buffet extends Thread{
public Compartiment[] buffet; public Buffet buffet;
public Employe_du_buffet(Compartiment[] buffet){
public Employe_du_buffet(Buffet buffet){
this.buffet = buffet; this.buffet = buffet;
this.setDaemon(true); this.setDaemon(true);
} }
/*
* vas faire le tour de tout les buffet
* si un a moins de 100g, si il n'est pas libre il wait dessus, sinon il le remplis
* avant de se réendormir il vérifit qu'aucun compartiment n'as été vidé pendant dans son dot
*/
public void run(){ public void run(){
while(Thread.currentThread().isDaemon()){ while(Thread.currentThread().isDaemon()){
for(int i = 0; i<buffet.length;i++){ for(int i = 0; i<buffet.length();i++){
if(buffet[i].getQuantite()<100){ Compartiment compartiment = buffet.getCompartiment(i);
try {
compartiment.getSemaphore().acquire();
if(compartiment.getQuantite()<100){
System.out.println( ansi().fgBlue().a("Employe Buffer").reset().a(": remplie de stand " + compartiment.getName() + ", il ne restait plus que " + compartiment.getQuantite() +" g"));
//System.out.println("Employe Buffer : remplie de stand " + compartiment.getName() + ", il ne restait plus que " + compartiment.getQuantite() +" g");
compartiment.remplir();
}
} catch (Exception e) {
e.printStackTrace();
} finally{
compartiment.getSemaphore().release();
}
}
synchronized(buffet){
if(!this.buffet.isEmpty()){
try { try {
while(!buffet[i].isLibre()){ buffet.wait();
buffet[i].wait();
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
System.out.println("Employe Buffer : remplie de stand " + buffet[i].getName() + ", il ne restait plus que " + buffet[i].getQuantite() +" g");
buffet[i].remplir();
} }
} }
} }
} }
} }

View File

@@ -1,42 +1,18 @@
public class Restaurant { public class Restaurant {
protected final int MAX_CLIENTS = 20; protected final int MAX_CLIENTS = 20;
public int nbClient; private int nbClient;
public Compartiment[] buffet = new Compartiment[4]; public Buffet buffet;
public Employe_du_buffet employeB; public Employe_du_buffet employeB;
public Stand_de_cuisson stand_de_cuisson; public Stand_de_cuisson stand_de_cuisson;
public Cuisinier cuisinier; public Cuisinier cuisinier;
/*
private Client[] clients= new Client[MAX_CLIENTS+5];
Restaurant(){
nbClient = 0;
for(int i = 0 ; i<buffet.length; i++){
this.buffet[i] = new Compartiment();
}
this.employeB = new Employe_du_buffet(buffet);
this.stand_de_cuisson = new Stand_de_cuisson();
this.cuisinier = new Cuisinier(stand_de_cuisson);
employeB.start();
cuisinier.start();
for(int i=0; i<clients.length; i++){
clients[i] = new Client(this);
clients[i].start();
}
}
*/
public Restaurant(){ public Restaurant(){
this.nbClient=0; this.nbClient=0;
this.buffet[0] = new Compartiment("poisson"); this.buffet = new Buffet();
this.buffet[1] = new Compartiment("viande");
this.buffet[2] = new Compartiment("légume");
this.buffet[3] = new Compartiment("nouille");
this.stand_de_cuisson = new Stand_de_cuisson(); this.stand_de_cuisson = new Stand_de_cuisson();
this.employeB = new Employe_du_buffet(buffet); this.employeB = new Employe_du_buffet(buffet);
this.cuisinier = new Cuisinier(stand_de_cuisson); this.cuisinier = new Cuisinier(stand_de_cuisson);
this.employeB.start(); this.employeB.start();

View File

@@ -1,30 +1,28 @@
import java.util.LinkedList;
import java.util.Queue;
public class Stand_de_cuisson { public class Stand_de_cuisson {
private Queue<Client> clients = new LinkedList<Client>();
private Client client_courant;
//get le client en tête de queue
public synchronized Client getClient(){ Stand_de_cuisson(){
return clients.peek(); this.client_courant = null;
} }
//supprime le client en tête de queue public void faire_cuire(Client client_courant) {
public synchronized void nextClient(){ this.client_courant = client_courant;
clients.poll(); notifyAll(); //pour réveiller de Cuisinier (notifyAll car des clients sont aussi en wait sur le stand)
} }
public synchronized void finir_cuit(){ public Client getClient() {
return client_courant;
}
/*
* libère la place
* prévient le client en attente que sont plat est fini, et les prochains client que la place est libre
*/
public void cuissonFini(){
this.client_courant = null;
notifyAll(); notifyAll();
} }
public synchronized void ajouter_client(Client client){
clients.add(client);
notifyAll();
}
public synchronized boolean containsClient(Client client){
return this.clients.contains(client);
}
} }