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
|
Le constructeur Restaurant initialise le Buffet : le Buffet qui initialise dans
|
||||||
son constructeur les 4 Compartiment (poisson, viande, légume et nouille), le
|
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
|
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 :
|
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 le
|
(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émaphore du compartiment est libre avant de lui-même le verrouiller,
|
||||||
s'être servi il déverrouille fait un notifyAll sur le compartiment pour
|
après s'être servi il déverrouille.
|
||||||
réveiller les clients et l'employer du buffet qui pourrait attendre.
|
|
||||||
Et fais aussi un notify sur le buffet pour que l'employé du buffet
|
Et fais aussi un notify sur le buffet pour que l'employé du buffet
|
||||||
puisse refaire un tour des compartiments.
|
puisse refaire un tour des compartiments.
|
||||||
(3) Cuire au stand, en se synchronisant avec le stand de cuisson.
|
(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
|
(5) Sort, en faisant un notifyAll sur le restaurant pour prévenir tout autre
|
||||||
thread client attendant pour entrer
|
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
|
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,
|
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.
|
le buffet le réveillera à chaque fois qu'un client se soit servi.
|
||||||
|
|
||||||
Difficulté :
|
Difficulté :
|
||||||
Nous n'avons pas vraiment rencontré de difficulté, on a juste eu parfois quelque
|
On avait commencé dans Stand_de_cuisson par faire une Queue, on a ensuite
|
||||||
oublie (notifyAll manquant par exemple).
|
|
||||||
On avait aussi 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
|
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
|
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.
|
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 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,18 +24,21 @@ 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){
|
public void prendre_portion(int i){
|
||||||
Compartiment compartiment = this.restaurant.buffet.getCompartiment(i);
|
Compartiment compartiment = this.restaurant.buffet.getCompartiment(i);
|
||||||
synchronized(compartiment){
|
Boolean servi = false;
|
||||||
int r =new Random().nextInt(MAX_PORTION);
|
int r =new Random().nextInt(MAX_PORTION);
|
||||||
|
//int r = Math.max(compartiment.getQuantite(),69); //TODO
|
||||||
|
while(!servi){
|
||||||
try{
|
try{
|
||||||
while(r > compartiment.getQuantite() || !compartiment.isLibre()){
|
compartiment.getSemaphore().acquire();
|
||||||
compartiment.wait();
|
if(r<=compartiment.getQuantite()){
|
||||||
}
|
|
||||||
} catch (InterruptedException e){
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
compartiment.setLibre(false);
|
|
||||||
compartiment.servir(r);
|
compartiment.servir(r);
|
||||||
try{
|
try{
|
||||||
long temps_servir =new Random().nextInt(300 - 200) + 200;
|
long temps_servir =new Random().nextInt(300 - 200) + 200;
|
||||||
@@ -43,16 +46,29 @@ public class Client extends Thread {
|
|||||||
}catch(InterruptedException e){
|
}catch(InterruptedException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
compartiment.setLibre(true);
|
System.out.println(this.getNameClient() + " : a pris une portion de " + compartiment.getName() + " " + r);
|
||||||
System.out.println(this.getNameClient() + " : a pris une portion de " + compartiment.getName());
|
servi = true;
|
||||||
|
}
|
||||||
compartiment.notifyAll();
|
}catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally{
|
||||||
|
compartiment.getSemaphore().release();
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
synchronized(this.restaurant.buffet){
|
synchronized(this.restaurant.buffet){
|
||||||
this.restaurant.buffet.notify();
|
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(){
|
public void entrer(){
|
||||||
synchronized(restaurant){
|
synchronized(restaurant){
|
||||||
try{
|
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(){
|
public void manger(){
|
||||||
try{
|
try{
|
||||||
System.out.println(this.getNameClient() + " : mange");
|
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(){
|
public void sort(){
|
||||||
synchronized(restaurant){
|
synchronized(restaurant){
|
||||||
System.out.println("- " + this.getNameClient() + " : sorti");
|
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){
|
||||||
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){
|
||||||
@@ -92,7 +121,7 @@ public class Client extends Thread {
|
|||||||
while(stand.getClient()!=null){
|
while(stand.getClient()!=null){
|
||||||
stand.wait();
|
stand.wait();
|
||||||
}
|
}
|
||||||
stand.entrerDansLaQueue(this);
|
stand.faire_cuire(this);
|
||||||
while(stand.getClient()==this){
|
while(stand.getClient()==this){
|
||||||
stand.wait();
|
stand.wait();
|
||||||
}
|
}
|
||||||
@@ -103,6 +132,7 @@ public class Client extends Thread {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = 200;
|
this.quantite_courant = 200;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.libre = true;
|
this.semaphore=new Semaphore(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void remplir(){
|
synchronized void remplir(){
|
||||||
@@ -17,7 +19,6 @@ public class Compartiment{
|
|||||||
|
|
||||||
synchronized void servir(int qte){
|
synchronized void servir(int qte){
|
||||||
quantite_courant -= qte;
|
quantite_courant -= qte;
|
||||||
notifyAll(); //pour que l'employé du buffet vérifit le buffet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getQuantite(){
|
public int getQuantite(){
|
||||||
@@ -28,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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ public class Cuisinier extends Thread {
|
|||||||
this.stand = stand;
|
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(){
|
||||||
synchronized(stand){
|
synchronized(stand){
|
||||||
while(Thread.currentThread().isDaemon()){
|
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){
|
public void faire_cuire(Client client){
|
||||||
System.out.println("# Cuisinier : 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();
|
||||||
|
|||||||
@@ -2,29 +2,36 @@ public class Employe_du_buffet extends Thread{
|
|||||||
|
|
||||||
public Buffet buffet;
|
public Buffet buffet;
|
||||||
|
|
||||||
|
|
||||||
public Employe_du_buffet(Buffet 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(){
|
||||||
synchronized(buffet){
|
|
||||||
while(Thread.currentThread().isDaemon()){
|
while(Thread.currentThread().isDaemon()){
|
||||||
for(int i = 0; i<buffet.length();i++){
|
for(int i = 0; i<buffet.length();i++){
|
||||||
Compartiment compartiment = buffet.getCompartiment(i);
|
Compartiment compartiment = buffet.getCompartiment(i);
|
||||||
|
|
||||||
if(compartiment.getQuantite()<100){
|
|
||||||
try {
|
try {
|
||||||
while(!compartiment.isLibre()){
|
compartiment.getSemaphore().acquire();
|
||||||
compartiment.wait();
|
if(compartiment.getQuantite()<100){
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
System.out.println("Employe Buffer : 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();
|
compartiment.remplir();
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally{
|
||||||
|
compartiment.getSemaphore().release();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized(buffet){
|
||||||
|
if(!this.buffet.isEmpty()){
|
||||||
try {
|
try {
|
||||||
buffet.wait();
|
buffet.wait();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -33,4 +40,6 @@ public class Employe_du_buffet extends Thread{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,18 +6,23 @@ public class Stand_de_cuisson {
|
|||||||
this.client_courant = null;
|
this.client_courant = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void entrerDansLaQueue(Client client_courant) {
|
public void faire_cuire(Client client_courant) {
|
||||||
notifyAll(); //pour réveiller de Cuisinier
|
|
||||||
this.client_courant = 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() {
|
public Client getClient() {
|
||||||
return client_courant;
|
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(){
|
public void cuissonFini(){
|
||||||
this.client_courant = null;
|
this.client_courant = null;
|
||||||
notifyAll(); //prévient le client en attente, et les prochains client
|
notifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user