Compare commits
3 Commits
Cuisinier_
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dac466702 | ||
|
|
aab11f6869 | ||
|
|
1a0c808353 |
Binary file not shown.
53
rapport.txt
53
rapport.txt
@@ -1,45 +1,32 @@
|
||||
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
|
||||
ainsi que le restaurant, puis on start tous les clients.
|
||||
|
||||
Le constructeur Restaurant initialise le Buffet : le Buffet qui initialise dans
|
||||
son constructeur les 4 Compartiment (poisson, viande, légume et nouille), le
|
||||
stand de cuisson, le Cuisinier, l'Employe_du_buffet. Puis il peut star l'employé
|
||||
du buffet et le Cuisinier.
|
||||
Le constructeur Restaurant initialise le Buffet, un tableau de 4 Compartiment
|
||||
(poisson, viande, légume et nouille), le stand de cuisson, l'Employe_du_buffet
|
||||
et le Cuisinier. Il star en suite start ces deux derniers.
|
||||
|
||||
Le run de Client va suivre ces étapes :
|
||||
(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 que
|
||||
le sémaphore du compartiment est libre avant de lui-même le verrouiller,
|
||||
après s'être servi il libère le sémaphore.
|
||||
Et fais aussi un notify sur le buffet pour que l'employé du buffet
|
||||
puisse refaire un tour des compartiments.
|
||||
(3) Cuire au stand, il "fait la queue" en attendant que la palce se libère,
|
||||
il wait sur le stand de cuisson en attendant d'être notify.
|
||||
(2) Prendre une portion de chaque Compartiment du buffet, en vérifiant
|
||||
le verrou du compartiment est libre avant de lui-même le verrouiller, après
|
||||
c'être servi il déverrouille fait un notifyAll pour réveiller les clients
|
||||
ou l'employer du buffet qui pourrait attendre.
|
||||
(3) Cuire au stand, en se mettant dans la queue (il notifyAll le stand pour
|
||||
réveiller le cuisinier), quand son plat est cuit le cuisinier le sort de la
|
||||
queue (le stand fait un notifyAll pour réveiller le client)
|
||||
(4) Manger
|
||||
(5) Sort, en faisant un notifyAll sur le restaurant pour prévenir tout autre
|
||||
thread client attendant pour entrer
|
||||
|
||||
L'employé du buffet fait le tour de chaque Compartiment du Buffet, s'il y a un
|
||||
un compartiment à moins de 100g alors il vérifie qu'il est libre (sémaphore) et
|
||||
le remplit. Après avoir fait un tour il fait sleep sur le buffet, le buffet le
|
||||
réveillera à chaque fois qu'un client se soit servi.
|
||||
Le run du cuisinier, fait une boucle pour vérifier si un client est présent en
|
||||
tête de la queue du stand de cuisson. Si oui, alors il fait cuire son plat.
|
||||
Une fois fini, il sort le client le la queue et fait faire un notifyAll au stand
|
||||
pour prévenir le client que son plat est fini.
|
||||
|
||||
Le Cusinier attend qu'il y est un client, si non il dors en écoutant le stand de
|
||||
cuisson. Quand un client est là il fait cuir son plat puis notifyAll pour pévenir
|
||||
à la fois le cient qui faisait cuir son plat et tout les client en attente.
|
||||
L'employer du buffet fait le tour de chaque compartiment du buffet, s'il y a un
|
||||
un buffet à moins de 100g alors il vérifie qu'il est libre (se met en wait sinon)
|
||||
et le remplit.
|
||||
|
||||
Difficulté :
|
||||
Nous avons pas vraiment rencontré de difficulté, on a juste eu parfois quelque
|
||||
oublie (notifyAll manquant par exemple)
|
||||
@@ -1,32 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import java.util.Random;
|
||||
import static org.fusesource.jansi.Ansi.*;
|
||||
|
||||
public class Client extends Thread {
|
||||
private int MAX_PORTION = 100;
|
||||
@@ -14,8 +13,8 @@ public class Client extends Thread {
|
||||
public void run(){
|
||||
try{
|
||||
entrer();
|
||||
for(int i = 0; i<this.restaurant.buffet.length(); i++){
|
||||
prendre_portion(i);
|
||||
for(int i = 0; i<this.restaurant.buffet.length; i++){
|
||||
prendre_portion(this.restaurant.buffet[i]);
|
||||
}
|
||||
cuir_au_stand(restaurant.stand_de_cuisson);
|
||||
manger();
|
||||
@@ -25,68 +24,45 @@ public class Client extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prendre une portion du compartiment i du buffet
|
||||
* 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){
|
||||
public void prendre_portion(Compartiment compartiment){
|
||||
synchronized(compartiment){
|
||||
int r =new Random().nextInt(MAX_PORTION);
|
||||
try{
|
||||
compartiment.getSemaphore().acquire();
|
||||
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;
|
||||
while(r > compartiment.getQuantite() || !compartiment.isLibre()){
|
||||
compartiment.wait();
|
||||
}
|
||||
}catch (Exception e) {
|
||||
} catch (InterruptedException e){
|
||||
e.printStackTrace();
|
||||
} finally{
|
||||
compartiment.getSemaphore().release();
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized(this.restaurant.buffet){
|
||||
this.restaurant.buffet.notify();
|
||||
compartiment.setLibre(false);
|
||||
compartiment.servir(r);
|
||||
try{
|
||||
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(){
|
||||
synchronized(restaurant){
|
||||
try{
|
||||
while(!restaurant.libre()){
|
||||
restaurant.wait();
|
||||
}
|
||||
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");
|
||||
System.out.println("+ " + this.getNameClient() + " : est entré dans le restaurant");
|
||||
restaurant.ajouterClient();
|
||||
}catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* le Thread s'endort pendant 1 à 2 s le temps de manger
|
||||
*/
|
||||
public void manger(){
|
||||
try{
|
||||
System.out.println(this.getNameClient() + " : mange");
|
||||
@@ -97,45 +73,30 @@ 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(){
|
||||
synchronized(restaurant){
|
||||
|
||||
System.out.println( ansi().fgRgb(255,0,0).a("- ").reset().a(this.getNameClient() + " : est sorti dans le restaurant"));
|
||||
//System.out.println("- " + this.getNameClient() + " : sorti");
|
||||
System.out.println("- " + this.getNameClient() + " : sorti");
|
||||
restaurant.diminuerClient();
|
||||
restaurant.notify();
|
||||
restaurant.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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){
|
||||
stand.ajouter_client(this);
|
||||
System.out.println(this.getNameClient() + " : attend pour faire cuir son plat");
|
||||
synchronized(stand){
|
||||
try{
|
||||
while(stand.getClient()!=null){
|
||||
while(stand.containsClient(this)){
|
||||
stand.wait();
|
||||
}
|
||||
stand.faire_cuire(this);
|
||||
while(stand.getClient()==this){
|
||||
stand.wait();
|
||||
}
|
||||
}catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}catch (InterruptedException e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
System.out.println(this.getNameClient() + " : le plat est cuit");
|
||||
|
||||
}
|
||||
|
||||
|
||||
public String getNameClient(){
|
||||
return ("Client " + this.id);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class Compartiment{
|
||||
protected final int QUANTITE_MAX = 1000;
|
||||
private int quantite_courant;
|
||||
private String name;
|
||||
private Semaphore semaphore;
|
||||
private boolean libre;
|
||||
|
||||
Compartiment(String name){
|
||||
this.quantite_courant = 200;
|
||||
this.quantite_courant = 500;
|
||||
this.name = name;
|
||||
this.semaphore=new Semaphore(1);
|
||||
this.libre = true;
|
||||
}
|
||||
|
||||
synchronized void remplir(){
|
||||
@@ -29,7 +27,11 @@ public class Compartiment{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Semaphore getSemaphore() {
|
||||
return semaphore;
|
||||
synchronized boolean isLibre(){
|
||||
return this.libre;
|
||||
}
|
||||
|
||||
synchronized void setLibre(boolean libre){
|
||||
this.libre = libre;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,45 @@
|
||||
import java.util.Random;
|
||||
import static org.fusesource.jansi.Ansi.*;
|
||||
|
||||
|
||||
public class Cuisinier extends Thread {
|
||||
Stand_de_cuisson stand;
|
||||
private Stand_de_cuisson stand;
|
||||
|
||||
public Cuisinier(Stand_de_cuisson stand){
|
||||
public Cuisinier(Stand_de_cuisson stand_de_cuisson){
|
||||
this.stand= stand_de_cuisson;
|
||||
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(){
|
||||
while(Thread.currentThread().isDaemon()){
|
||||
attendreClient();
|
||||
}
|
||||
}
|
||||
|
||||
private void attendreClient(){
|
||||
Client client = stand.getClient();
|
||||
synchronized(stand){
|
||||
while(Thread.currentThread().isDaemon()){
|
||||
Client client = stand.getClient();
|
||||
if(client!=null){
|
||||
faire_cuire(client);
|
||||
}
|
||||
else{
|
||||
try {
|
||||
stand.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try{
|
||||
while(client==null){
|
||||
stand.wait();
|
||||
client= stand.getClient();
|
||||
}
|
||||
}
|
||||
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){
|
||||
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()) ;
|
||||
System.out.println("# Cuisinier : fait cuire le plat de " + client.getNameClient()) ;
|
||||
try{
|
||||
long temps_cuire =new Random().nextInt(400 - 200) + 200;
|
||||
long temps_cuire =new Random().nextInt(300 - 100) + 100;
|
||||
Thread.sleep(temps_cuire);
|
||||
}catch(InterruptedException e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println( ansi().fgRed().a("Cuisinier").reset().a(": a fini de cuire le plat de " + client.getNameClient()));
|
||||
|
||||
//System.out.println("# Cuisinier : a fini de cuire le plat de " + client.getNameClient()) ;
|
||||
stand.cuissonFini();
|
||||
System.out.println("# Cuisinier : a fini de cuire le plat de " + client.getNameClient()) ;
|
||||
stand.nextClient();
|
||||
stand.finir_cuit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,27 @@
|
||||
import static org.fusesource.jansi.Ansi.*;
|
||||
|
||||
public class Employe_du_buffet extends Thread{
|
||||
|
||||
public Buffet buffet;
|
||||
public Compartiment[] buffet;
|
||||
|
||||
|
||||
public Employe_du_buffet(Buffet buffet){
|
||||
public Employe_du_buffet(Compartiment[] buffet){
|
||||
this.buffet = buffet;
|
||||
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(){
|
||||
while(Thread.currentThread().isDaemon()){
|
||||
for(int i = 0; i<buffet.length();i++){
|
||||
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()){
|
||||
for(int i = 0; i<buffet.length;i++){
|
||||
if(buffet[i].getQuantite()<100){
|
||||
try {
|
||||
buffet.wait();
|
||||
while(!buffet[i].isLibre()){
|
||||
buffet[i].wait();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,42 @@
|
||||
public class Restaurant {
|
||||
protected final int MAX_CLIENTS = 20;
|
||||
|
||||
private int nbClient;
|
||||
public int nbClient;
|
||||
|
||||
public Buffet buffet;
|
||||
public Compartiment[] buffet = new Compartiment[4];
|
||||
public Employe_du_buffet employeB;
|
||||
public Stand_de_cuisson stand_de_cuisson;
|
||||
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(){
|
||||
this.nbClient=0;
|
||||
this.buffet = new Buffet();
|
||||
this.buffet[0] = new Compartiment("poisson");
|
||||
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.employeB = new Employe_du_buffet(buffet);
|
||||
this.cuisinier = new Cuisinier(stand_de_cuisson);
|
||||
this.employeB.start();
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class Stand_de_cuisson {
|
||||
private Queue<Client> clients = new LinkedList<Client>();
|
||||
|
||||
private Client client_courant;
|
||||
|
||||
Stand_de_cuisson(){
|
||||
this.client_courant = null;
|
||||
|
||||
//get le client en tête de queue
|
||||
public synchronized Client getClient(){
|
||||
return clients.peek();
|
||||
}
|
||||
|
||||
public void faire_cuire(Client client_courant) {
|
||||
this.client_courant = client_courant;
|
||||
notifyAll(); //pour réveiller de Cuisinier (notifyAll car des clients sont aussi en wait sur le stand)
|
||||
|
||||
//supprime le client en tête de queue
|
||||
public synchronized void nextClient(){
|
||||
clients.poll();
|
||||
}
|
||||
|
||||
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;
|
||||
public synchronized void finir_cuit(){
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized void ajouter_client(Client client){
|
||||
clients.add(client);
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized boolean containsClient(Client client){
|
||||
return this.clients.contains(client);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user