sémaphore sur les compatiments
This commit is contained in:
16
rapport.txt
16
rapport.txt
@@ -7,14 +7,13 @@ 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 Cusinier, l'Employe_du_buffet. Puis il star en suite start
|
||||
l'employer du buffet.
|
||||
l'employé du buffet.
|
||||
|
||||
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 le
|
||||
verrou du compartiment est libre avant de lui-même le verrouiller, après
|
||||
s'être servi il déverrouille fait un notifyAll sur le compartiment pour
|
||||
réveiller les clients et l'employer du buffet qui pourrait attendre.
|
||||
sémaphore du compartiment est libre avant de lui-même le verrouiller,
|
||||
après s'être servi il déverrouille.
|
||||
Et fais aussi un notify sur le buffet pour que l'employé du buffet
|
||||
puisse refaire un tour des compartiments.
|
||||
(3) Cuire au stand, en se synchronisant avec le stand de cuisson.
|
||||
@@ -22,15 +21,16 @@ Le run de Client va suivre ces étapes :
|
||||
(5) Sort, en faisant un notifyAll sur le restaurant pour prévenir tout autre
|
||||
thread client attendant pour entrer
|
||||
|
||||
L'employer du buffet fait le tour de chaque Compartiment du Buffet, s'il y a un
|
||||
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 (se met en wait
|
||||
desus sinon) 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.
|
||||
|
||||
Difficulté :
|
||||
Nous n'avons pas vraiment rencontré de difficulté, on a juste eu parfois quelque
|
||||
oublie (notifyAll manquant par exemple).
|
||||
On avait aussi commencé dans Stand_de_cuisson par faire une Queue, on a ensuite
|
||||
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)
|
||||
|
||||
@@ -18,4 +18,15 @@ public class Buffet {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,35 +24,51 @@ 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);
|
||||
synchronized(compartiment){
|
||||
int r =new Random().nextInt(MAX_PORTION);
|
||||
Boolean servi = false;
|
||||
int r =new Random().nextInt(MAX_PORTION);
|
||||
//int r = Math.max(compartiment.getQuantite(),69); //TODO
|
||||
while(!servi){
|
||||
try{
|
||||
while(r > compartiment.getQuantite() || !compartiment.isLibre()){
|
||||
compartiment.wait();
|
||||
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;
|
||||
}
|
||||
} catch (InterruptedException e){
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally{
|
||||
compartiment.getSemaphore().release();
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
synchronized(this.restaurant.buffet){
|
||||
this.restaurant.buffet.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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{
|
||||
@@ -67,6 +83,9 @@ public class Client extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* le Thread s'endort pendant 1 à 2 s le temps de manger
|
||||
*/
|
||||
public void manger(){
|
||||
try{
|
||||
System.out.println(this.getNameClient() + " : mange");
|
||||
@@ -77,14 +96,24 @@ 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("- " + this.getNameClient() + " : sorti");
|
||||
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){
|
||||
System.out.println(this.getNameClient() + " : attend pour faire cuir son plat");
|
||||
synchronized(stand){
|
||||
@@ -92,7 +121,7 @@ public class Client extends Thread {
|
||||
while(stand.getClient()!=null){
|
||||
stand.wait();
|
||||
}
|
||||
stand.entrerDansLaQueue(this);
|
||||
stand.faire_cuire(this);
|
||||
while(stand.getClient()==this){
|
||||
stand.wait();
|
||||
}
|
||||
@@ -103,6 +132,7 @@ public class Client extends Thread {
|
||||
System.out.println(this.getNameClient() + " : le plat est cuit");
|
||||
}
|
||||
|
||||
|
||||
public String getNameClient(){
|
||||
return ("Client " + this.id);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class Compartiment{
|
||||
protected final int QUANTITE_MAX = 1000;
|
||||
private int quantite_courant;
|
||||
private String name;
|
||||
private boolean libre;
|
||||
private Semaphore semaphore;
|
||||
|
||||
Compartiment(String name){
|
||||
this.quantite_courant = 200;
|
||||
this.name = name;
|
||||
this.libre = true;
|
||||
this.semaphore=new Semaphore(1);
|
||||
}
|
||||
|
||||
synchronized void remplir(){
|
||||
@@ -17,7 +19,6 @@ public class Compartiment{
|
||||
|
||||
synchronized void servir(int qte){
|
||||
quantite_courant -= qte;
|
||||
notifyAll(); //pour que l'employé du buffet vérifit le buffet
|
||||
}
|
||||
|
||||
public int getQuantite(){
|
||||
@@ -28,11 +29,7 @@ public class Compartiment{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
synchronized boolean isLibre(){
|
||||
return this.libre;
|
||||
}
|
||||
|
||||
synchronized void setLibre(boolean libre){
|
||||
this.libre = libre;
|
||||
public Semaphore getSemaphore() {
|
||||
return semaphore;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@ public class Cuisinier extends Thread {
|
||||
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(){
|
||||
synchronized(stand){
|
||||
while(Thread.currentThread().isDaemon()){
|
||||
@@ -26,10 +30,14 @@ public class Cuisinier extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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("# Cuisinier : fait cuire le plat de " + client.getNameClient()) ;
|
||||
try{
|
||||
long temps_cuire =new Random().nextInt(300 - 100) + 100;
|
||||
long temps_cuire =new Random().nextInt(400 - 200) + 200;
|
||||
Thread.sleep(temps_cuire);
|
||||
}catch(InterruptedException e){
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -2,35 +2,44 @@ public class Employe_du_buffet extends Thread{
|
||||
|
||||
public Buffet buffet;
|
||||
|
||||
|
||||
public Employe_du_buffet(Buffet 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(){
|
||||
synchronized(buffet){
|
||||
while(Thread.currentThread().isDaemon()){
|
||||
for(int i = 0; i<buffet.length();i++){
|
||||
Compartiment compartiment = buffet.getCompartiment(i);
|
||||
|
||||
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){
|
||||
try {
|
||||
while(!compartiment.isLibre()){
|
||||
compartiment.wait();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("Employe Buffer : remplie de stand " + compartiment.getName() + ", il ne restait plus que " + compartiment.getQuantite() +" g");
|
||||
compartiment.remplir();
|
||||
}
|
||||
}
|
||||
try {
|
||||
buffet.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally{
|
||||
compartiment.getSemaphore().release();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(buffet){
|
||||
if(!this.buffet.isEmpty()){
|
||||
try {
|
||||
buffet.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,23 @@ public class Stand_de_cuisson {
|
||||
this.client_courant = null;
|
||||
}
|
||||
|
||||
public void entrerDansLaQueue(Client client_courant) {
|
||||
notifyAll(); //pour réveiller de Cuisinier
|
||||
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)
|
||||
|
||||
}
|
||||
|
||||
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(); //prévient le client en attente, et les prochains client
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user