P. Pfahler, E. Stümpel

Programmieren in Java, Winter 1997/98

9. Übungsblatt, Lösungsvorschlag


Aufgabe 15 (Produzent/Konsument)

In der Vorlesung wurde eine Java-Lösung für das Produzent-/Konsument-Szenario für den Fall des auf einen Eintrag beschränkten Zwischenpuffers behandelt. Die Klasse Puffer sollte so erweitert werden, daß Puffer beliebiger Kapazität möglich werden. Die gewünschte Kapazität ist bei der Konstruktion von Puffer-Objekten anzugegeben.

Die erweiterte Version von Puffer.java mit LIFO - Prinzip:


//Puffer.java

class Puffer {
  // Puffer der Groesse size zwischen 
  // Produzent und Konsument
  private int inhalt[];
  private int anzahl = 0;
  private int max;

  public Puffer() {
   this(1);			//1-elementiger Puffer
  }
  
  public Puffer(int size) {	//Puffer der Groesse size
    inhalt = new int[size];
    anzahl = 0;
    max = size;
  }
  
  public boolean empty() {	//Puffer leer?
    return anzahl == 0;
  }

  public boolean full () {	//Puffer voll?
    return anzahl == max;
  }

  public synchronized int get() {
    int wert;
    while ( empty() ) {		//warte solange Puffer leer
      try {
        wait();
      } catch (InterruptedException e) { }
    }
    anzahl--;			//jetzt letztes Element holen
    wert = inhalt[anzahl];
    notifyAll();		//Sperre aufgehoben -> wartende Threads werden ausführbereit
    return wert;
  }
  
  public synchronized void put(int wert) {
    while ( full() ) {		//warte solange Puffer voll
      try {
        wait();
      } catch (InterruptedException e) { }
    }
    inhalt[anzahl] = wert;	//jetzt ein Element ablegen
    anzahl++;
    notifyAll();		//Sperre aufgehoben -> wartende Threads werden ausführbereit
  }
}

Ein Testlauf liefert das folgende Ausgabeprotokoll:

Produzent gibt: 0
Konsument nimmt 0
Produzent gibt: 1
Produzent gibt: 2
Produzent gibt: 3
Produzent gibt: 4
Konsument nimmt 4
Konsument nimmt 3
Konsument nimmt 2
Konsument nimmt 1

Die vollständige Produzent-/Konsument-Version zum Mitnehmen: Bemerkung: Die Ausgabe "Produzent gibt ..." und "Konsument nimmt ..." wurde in die synchronisierten Methoden get und put der Pufferklasse verlagert, da ohne Synchronisation keine korrekte Ausgabereihenfolge sicherzustellen ist. Bevor die Ausgabe nach einer put - oder get - Operation erfolgt ist, könnte schon wieder ein Thread den kritischen Bereich durchlaufen haben und die zugehörige Ausgabe erfolgt sein. Die Ausgabe würde nicht mehr dem tatsächlichem Ablauf entsprechen.

Aufgabe 16 (Animation Produzent/Konsument)

Hier sollte eine animmierte Darstellung des Produzent-/Konsument-Szenarios in Form eines Java-Applets entwickelt werden. Hierzu wurden viele wirklich gute Animationen abgeben und wir stellen nun hier eine vor die uns besonders gut gefallen hat:

Dieses Applet wurde entwickelt von Holger Bunzel und Lars Steinfurth.

Die Sourcen zum Mitnehmen: