RETT PÅ JAVA
     
 



     Eksempler og løsninger   
     Java og easyIO   
     Retteliste   
     Undervisning   
     Hjelp   
     Om boka   
     Forsiden   
                      



/* Løsningsforslag oppgave 2 og 3, kapittel 17.
 * Lagres på fil Restaurant.java
 * 
 * Feilen oppstår i den ene kokken har sjekket at fler tallerkner skal
 * leveres og går inn i while løkken. Før kallet på rest.putTallerken
 * er det ingen lås, og den andre kokken rekker å komme inn i sin
 * while-løkke. Dermed vil begge kokkene befinne seg i while-løkka og
 * det blir produsert minst en tallerken for mye. Det hjelper med
 * andre ord ikke at kokkFerdig-metoden er synkronisert, så lenge
 * kokken slipper låsen før kallet på putTallerken-metoden.
 *
 * En mulig løsning er å legge kallet på kokkFerdig-metoden i
 * putTallerken-metoden. Hvis vi i tillegg lar putTallerken-metoden
 * returnere svaret fra kokkFerdig-metoden kan vi bruke denne som
 * betingelsen i while-løkka.
 */


public class Restaurant {
    int antBestilt;
    int antLaget = 0, antServert = 0; // tallerkenrertter
    int antKokker = 5, antServitører = 7;

    Restaurant(int ant) {
	antBestilt = ant;
	for (int i = 0; i < antKokker; i++) {
	    Kokk k = new Kokk(this, "Kokk nr. " + i);
	    k.start();
	}
	
	for (int i = 0; i < antServitører; i++) {
	    Servitor s = new Servitor(this, "Servitør nr. " + i);
	    s.start();
	}
	
    }

    public static void main(String[] args) {
	new Restaurant(Integer.parseInt(args[0]));
    }

    synchronized boolean kokkFerdig() {
	return antLaget == antBestilt;
    }

    synchronized boolean servitørFerdig() {
	return antServert == antBestilt;
    }

    synchronized boolean putTallerken(Kokk k) {
	// Kokketråden blir eier av låsen.

	while (antLaget - antServert >= 2) {
	    /* så lenge det er minst 2 tallerkner
	     * som ikke er servert, skal kokken vente. */
	    try {
		wait(); /* Kokketråden gir fra seg 
			 * låsen og sover til den 
			 * blir vekket */
	    } catch (InterruptedException e) {}
	    // Kokketråden blir igjen eier av låsen

	}

	boolean ferdig = kokkFerdig();
	if (!ferdig) {
	    antLaget++;
	    System.out.println(k.getName() + " laget nr: " + antLaget);
	}
	
	notify(); /* Si ifra til servitøren. */

	return !ferdig;
    }

    synchronized boolean getTallerken(Servitor s) {
	// Servitørtråden blir eier av låsen.
	
	while (antLaget == antServert && !servitørFerdig()) {
	    /* så lenge kokken ikke har plassert 
	     * en ny tallerken. Dermed skal 
	     * servitøren vente. */
	    try {
		wait(); /* Servitørtråden gir fra seg
			 * låsen og sover til den
			 * blir vekket */
	    } catch(InterruptedException e) {}
	    // Servitørtråden blir igjen eier av låsen.
	}

	boolean ferdig = servitørFerdig();
	if (!ferdig) {
	    antServert++;
	    System.out.println(s.getName() + " serverer nr: " + antServert);
	}


	notify(); /* si ifra til kokken */
	return !ferdig;
    }
}

class Kokk extends Thread {
    Restaurant rest;
    
    Kokk(Restaurant rest, String navn) { 
	super(navn); // Denne tråden heter nå 
	this.rest = rest;
    }

    public void run() {
	while (rest.putTallerken(this)) {
	    // levert tallerken.
	    
	    try {
		sleep((long) (1000 * Math.random()));
	    } catch (InterruptedException e) {}
	}
	// Kokken er ferdig
    }
}

class Servitor extends Thread {
    Restaurant rest;

    Servitor(Restaurant rest, String navn) {
	super(navn); // Denne tråden heter nå 
	this.rest = rest;
    }

    public void run() {
	while (rest.getTallerken(this)) {
	    try {
		sleep((long) (1000 * Math.random()));
	    } catch (InterruptedException e) {}
	}
	// Servitøren er ferdig

    }
}


Tilbake