Java Threads - Wait Notify - Verständnisproblem

.micha

Neues Mitglied
Liebes Forum,

ich versuche gerade mich mit den Threads in Java anzufreunden, aber irgendwie klappt es nicht so wie es soll. Ich habe hier ein Beispielprogramm bestehend aus der Klasse Lager, sowie den Klassen Produzent und Konsument die jeweils von der Klasse Thread abgeleitet wurden und Zugriff auf das Lager haben.

Dier Klasse Lager:
Java:
public class Lager 
{
    // Ein Zähler für die Anzahl der Produkte im Lager
    private int prodcnt = 0;
    private boolean pause = false;
    
    // Methode produzieren
    public synchronized void produzieren()
    {
        if (pause == false)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e) {}        
        
            prodcnt++;
            System.out.println("Neues Produkt " + prodcnt + " hergestellt");
            pause = true;
            notifyAll();
        } 
        else System.out.println("Der Produzent muss warten"); 
    }
    
    // Methode konsumieren  
    public synchronized void konsumieren()
    {
        if (pause == true)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e) {}        
      
            prodcnt--;
            System.out.println("Habe Produkt Nummer " + prodcnt + " entnommen");
            pause = false;
            notifyAll();
        }
        else System.out.println("Der Konsument muss warten.");
    }   
}

Der Produzent:
Java:
public class Produzent extends Thread
{
    Lager lagerObjekt;
    
    public Produzent(Lager lagerObjekt)
    {
        this.lagerObjekt = lagerObjekt;
    }
    
    public void run()
    {
        for (int i = 0; i < 10; i++)
        {
            lagerObjekt.produzieren();
            try
            {
                sleep((int)(Math.random()*1000));;
            }
            catch (InterruptedException e) {}
        }
    }   
}


Der Konsument
Java:
public class Konsument extends Thread 
{
    Lager lagerObjekt;
    
    public Konsument(Lager lagerObjekt)
    {
        this.lagerObjekt = lagerObjekt;
    }
    
    public void run()
    {
        for (int i = 0; i < 10; i++)
        {
            lagerObjekt.konsumieren();
            try
            {
                sleep((int)(Math.random()*1000));;
            }
            catch (InterruptedException e) {}
        }
    }
}

Wenn ich das über eine DemoKlasse ausführe:
Java:
public class Demo 
{
    public static void main(String args[])
    {
        // Lagersklaven für die Arbeit erstellen und an den produzierenden 
        // und den konsumierenden Thread übergeben.
        Lager l = new Lager();
      
        Produzent p = new Produzent(l);
        Konsument k = new Konsument(l);
        
        //Threads starten
        p.start();
        k.start();
    }
    
}

Dann bekomme ich leider immer nur gesagt: der Konsument muss warten
Scheint also was verkehrt zu sein 🙂

Vielen Dank schonmal fürs lesen
 
schau dir doch deinen Code an, bzw. beschreibe wie du dir den Ablauf vorstellst,
wenn du ohne Plan die Bausteine mit wait, notify, pause, sleep zusammbaust, dann kann es nicht klappen

pause ist zu beginn auf false, der Produzent darf rein, aber macht dann nichts weiter als zu warten, worauf?
der Konsument wird immer per else abgeleht, würde er reinkommen, etwa weil pause umgestellt wird, würde er auch
bis in alle Ewigkeit warten, wer soll wen wann wie warum wecken?
das muss alles konzeptuell durchdacht werden, sonst geht nix

oder intelligenter kopieren, etwa von
http://www.cin.ufpe.br/~java/docs/tutorial/essential/threads/synchronization.html
dort wartet der Producer wenn etwas da ist, dann kann er sich nämlich sicher sein, dass der Konsument bald (ohne zu warten) was abholt und notifyAll() aufruft,
ist nichts da legt der Producer selber was ab und ruft notify auf, sollte ein Konsument gerade warten wird dieser geweckt und kann weiter machen,
falls nicht verpufft das notify wirkungslos, aber nicht schlimm, der Konsument wird bei seinem nächsten Besuch nicht warten, weil ja nun schon was da ist
 
Danke für den Link.
Habs nun abgeändert und vor allem meine fehlerhafte if-Anweisung durch while ersetzt. Sieht nun so aus, und es scheint zu funktionieren.

Java:
public class Lager 
{
    // einen Produktzaehler und Schalter für die Pausen
    private int zaehler = 0;
    private boolean pause = false;
    
    // die Methode Produzieren
    public synchronized void produzieren()
    {
        // in der Pause wartet der Prodzent
        while (pause == true)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e) {}
        }
        // Hier der Code für den Thread Prodzent, der den Zähler hochzählt
        zaehler++;
        System.out.println("Produkt" + zaehler + " erstellt");
        // Jetzt macht der Prodzent Pause und der Konsument weiter
        pause = true;
        notifyAll();
    }
    
    // die Methode Konsumieren
    public synchronized void konsumieren()
    {
        while (pause == false)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e) {}
        }
        // Hier der Code für den Thread Konsument der den Zähler runterzählt
        System.out.println("Produkt" + zaehler + " konsumiert");
        // Jetzt macht der Konsument Pause und der Hersteller weiter
        pause = false;
        notifyAll();
    }
}
 
nur die pause-Variable ist vielleicht noch undeutlich,
wenn du diese in produktVorhanden umbenennst, wäre verständlicher, wer was auf true oder false setzt bzw. bei true oder false wartet

[c]while (bool == true)[/c] geht übrigens auch als [c]while (bool)[/c]
[c]while (bool == false)[/c] dann [c]while (!bool)[/c]
 
Zuletzt bearbeitet von einem Moderator:

Zurück
Oben