Synchronisation eines kleinen Museums

BodyLAB

Bekanntes Mitglied
Hallo zusammen,

ich hab eine kleine Aufgabe die wie folgt ausschaut:
Ein Museum ermöglicht Besuchern den Eingang durch den Osteingang und den Ausgang durch den Westausgang.
An- und Abreise werden dem Museumsleiter über das Drehkreuze am Ein- und Ausgang signalisiert.
Wenn das Museum geöffnet ist, signalisiert der Museumsdirektor dem Controller, dass das Museum geöffnet ist, und
der Controller öffnet dann die Ankünfte und Abreisen.
Zum Zeitpunkt der Schließung signalisiert der Direktor, dass das Museum geschlossen ist.
Jetzt lässt der Lotse nur noch Abfahrten zu.


Öffnung um 9:00 Uhr und Schließung um 16:00 Uhr.
Aufgrund der aktuellen Pandemie-Situation achten Sie darauf, dass nur 50 Besucher gleichzeitig das Museum betreten dürfen.

Das Problem versuche ich gerade zu Lösen, nur habe ich ein Problem und weiß nicht ob es vielleicht an der Gepufferten Ausgabe liegt oder ob mein Programmcode ganz einfach misst ist.

Insgesamt habe ich derzeit 4 Klassen. Es fehlen noch ein paar Sachen aus der Übung die noch implementiert werden müssten, das Grundgerüst sieht so aus:
Java:
public class Eingang extends Thread {
    private Controller c;
    private int max = 50;

    public Eingang(Controller c) {
        this.c = c;
        this.start();
    }

    public void run() {
        while (c.museumOffen()) {
            if (c.getCount() < max)
                c.museumBetretten();
        }
    }
}

Java:
public class Ausgang extends Thread {
    private Controller c;

    public Ausgang(Controller c) {
        this.c = c;
        this.start();
    }

    public void run() {
        while (c.museumOffen()) {
                c.museumVerlassen();
        }
    }
}

Java:
public class Direktor extends Thread {
    private Controller c;

    public Direktor(Controller c) {
        this.c = c;
        this.start();
    }

    public void run() {
        try {
            c.museumWirdGeoeffnet();

            sleep(100);

            c.museumWirdGeschlossen();
        } catch (InterruptedException e) {
            e.getStackTrace();
        }

    }
}

Java:
public class Controller {
    private boolean offen;
    private int count;
    
    public synchronized void museumWirdGeoeffnet() {
        System.out.println("Der Direktor oeffnet das Museum");
        offen = true;
    }
    
    public synchronized boolean museumOffen() {
        return offen;
    }
    
    public synchronized void museumWirdGeschlossen() {
        System.out.println("Der Direktor schliesst das Museum");
        offen = false;
    }
    
    public synchronized int getCount() {
        return count;
    }
    
    public synchronized void museumBetretten() {
        while(count > 10) {
            try {
                wait();
            }catch(InterruptedException e) {
                e.getStackTrace();
            }
        }
        count++;
        System.out.println("Besucher " + count + " betritt das Museum");
    }
    
    public synchronized void museumVerlassen() {
        if(count > 0) {
            count--;
            System.out.println("Besucher " + count + " verlaesst das Museum");
        }
        notify();
    }   
    
    public static void main(String[] args) {
        Controller c = new Controller();
        Direktor d = new Direktor(c);
        Eingang e = new Eingang(c);
        Ausgang a = new Ausgang(c);
    }

}

In meiner Ausgabe gibt es Besucher die das Museum betreten obwohl es geschlossen wurde. Ist das mein verschulden oder liegt es am System.out.print?
Ausgabe schaut so aus:
Der Direktor oeffnet das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Besucher 1 betritt das Museum
Besucher 2 betritt das Museum
Besucher 3 betritt das Museum
Besucher 4 betritt das Museum
Besucher 5 betritt das Museum
Besucher 6 betritt das Museum
Besucher 7 betritt das Museum
Besucher 8 betritt das Museum
Besucher 9 betritt das Museum
Besucher 10 betritt das Museum
Besucher 11 betritt das Museum
Besucher 10 verlaesst das Museum
Besucher 9 verlaesst das Museum
Besucher 8 verlaesst das Museum
Besucher 7 verlaesst das Museum
Besucher 6 verlaesst das Museum
Besucher 5 verlaesst das Museum
Besucher 4 verlaesst das Museum
Besucher 3 verlaesst das Museum
Besucher 2 verlaesst das Museum
Besucher 1 verlaesst das Museum
Besucher 0 verlaesst das Museum
Der Direktor schliesst das Museum
Besucher 1 betritt das Museum
 
In der Klasse Eingang schickst du 50 Besucher in das Museum. Das entspricht aber nicht der Aufgabe. Es können auch 1000 Besucher am Tag kommen - aber eben nur 50 Besucher gleichzeitig das Museum betreten. Du limitierst die Besucherzahl aber auf 11, wenn ich das richtig lese.
 
Es ist nicht üblich eine Klasse von Thread abzuleiten. Normalerweise implementiert man Runnable und verwendet den entsprechenden Konstruktor der Klasse Thread. Programmierung sollte immer gegen Interfaces erfolgen, wenn das irgendwie möglich ist.
Der Name 'c' ist kein geeigneter Variablenname und macht den Code unleserlich.
 
Danke für die schnelle Antwort.
Einige Probleme habe ich jetzt noch.

Zum einen weiß ich nicht so recht wie ich das hin bekomme das es ein kommen und gehen von Threads ist. Sprich so das dort steht
Besucher 14 betritt das Museum
Besucher 6 verlaesst das Museum
Besucher 17 betritt das Museum
Besucher 7 betritt das Museum
Besucher 14 verlaesst das Museum

Glaube aber dann müsste ich das ganze komplett umbauen (verkomplizieren 😀) oder?

Dann versuche ich die ganze Zeit das mehr Leute das Museum besuchen können ohne das mehr als 50 Besucher sich im Museum befinden doch das klappt nicht.

Wie beim Eingang habe ich beim Ausgang auch noch das Problem mit der Ausgabe. Es kommt vor das Besucher im Museum eingesperrt werden und das welche noch das Museum verlassen nachdem es geschlossen wurde.
In der Aufgabenstellung steht nicht genau drin wie man das umsetzten soll. Ich würde nun simpel wie ich bin 😀 In der Direktor Klasse eine Methode im Monitor aufrufen c.besucherRausKehren(). Diese ruft dann museumVerlassen auf. Nur weiß ich nicht ob das erlaubt wäre 😀

Ist es normal das man sich mit Parallelität so schwer tut? Ich beschäftige mich jetzt schon seit gut 3 Monaten damit (gut ich war 6 Wochen Krank) doch habe das Gefühl als hätte ich nichts gelernt :-(

Normalerweise implementiert man Runnable und verwendet den entsprechenden Konstruktor der Klasse Thread. Programmierung sollte immer gegen Interfaces erfolgen, wenn das irgendwie möglich ist.
Das wusste ich noch überhaupt nicht. Werde das ändern. Brauch dann im Konstruktor nur new Thread(runnable).start() aufrufen 🙂
 
Also ich denke dein Museum muss etwas wie eine Liste/Stack/Array von Besuchern enthalten. dieser darf nicht größer sein als 50. Wenn in dem Stack Besucher enthalten sind, dann müssen diese nach einer gewissen Zeit entfernt werden. Ich denke das Museum ist eine Klasse für welche ein Thread erforderlich ist. Jeder Besucher muss einen Zeitstempel enthalten, wann das Museum betreten wurde. Wenn der Besucher eine gewisse Anwesenheitszeit überschritten hat, dann wird er rausgeschickt.
Dann fehlt also noch die Logik, welche verhindert, dass das Museum überfüllt wird. Das hast du ja schon Ansatzweise umgesetzt.
 
3 Monate ist gar nichts. Eher 3 Jahre.
Du lernst schon viel, aber du merkst ja auch, dass es immer noch viel mehr zu lernen gibt.
Das macht etwas Mut 🙂

Du kannst dir mal Deadlock Empire ansehen um sicher zu gehen dass du die Grundlagen mal verstanden hast.
Werde ich mir mal anschauen ;-) Doch ich bin mir sicher das dort vieles ist was ich noch nicht so genau verstehe :-(
Hab leider zu dem Thema auch nur zwei Deutsche Bücher hier liegen! Und da hab ich auch öfters mal ein Fragezeichen im Kopf.

Also ich denke dein Museum muss etwas wie eine Liste/Stack/Array von Besuchern enthalten. dieser darf nicht größer sein als 50. Wenn in dem Stack Besucher enthalten sind, dann müssen diese nach einer gewissen Zeit entfernt werden. Ich denke das Museum ist eine Klasse für welche ein Thread erforderlich ist. Jeder Besucher muss einen Zeitstempel enthalten, wann das Museum betreten wurde. Wenn der Besucher eine gewisse Anwesenheitszeit überschritten hat, dann wird er rausgeschickt.
Dann fehlt also noch die Logik, welche verhindert, dass das Museum überfüllt wird. Das hast du ja schon Ansatzweise umgesetzt.
Das werde ich gleich mal Probieren. Erst einmal habe ich jetzt alles verbessert doch leider auch immer noch einen Fehler (gerne auch mehr).
Wenn ich das if (c.getCount() < max) aus dem Eingang nehme, gibt es wieder Leute die rein gehen können obwohl zu ist :-( Somit stehen vor dem Eingang wohl immer nur 50 Leute was etwas doof ist :-( Hätte es auch lieber so das wenn um 9 Uhr 1000 Leute vor dem Eingang stehen aber nur 50 rein dürfen wieder 100 nach kommen könnten und dann eben 1050 vor der Tür stehen etc. ;-)

Hier jetzt mal meine neue Version:
Java:
public class Controller {
    private boolean offen, rausKehren;
    private int count;

    public synchronized void museumWirdGeoeffnet() {
        System.out.println("Der Direktor oeffnet das Museum");
        offen = true;
    }
    
    public synchronized boolean getRausKehren() {
        return rausKehren;
    }

    public synchronized boolean museumOffen() {
        return offen;
    }

    public synchronized void museumWirdGeschlossen() {
        while(count > 0) {
            try {
                wait();
            }catch(InterruptedException e) {
                e.getStackTrace();
            }
        }
        rausKehren = false;
        System.out.println("Der Direktor schliesst das Museum");
    }

    public synchronized int getCount() {
        return count;
    }

    public synchronized void museumBetretten() {
        if (offen) {
            while (count > 50) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.getStackTrace();
                }
            }
            count++;
            System.out.println("Besucher " + count + " betritt das Museum");
        }
    }

    public synchronized void museumVerlassen() {
        if (count > 0) {
            System.out.println("Besucher " + count + " verlaesst das Museum");
            count--;
        }

        notify();
    }
    
    public synchronized void rausKehren() {
        offen = false;
        rausKehren = true;
        notify();
    }

    public static void main(String[] args) {
        Controller c = new Controller();
        Direktor d = new Direktor(c);
        Eingang e = new Eingang(c);
        Ausgang a = new Ausgang(c);
    }

}

public class Ausgang implements Runnable {
    private Controller c;

    public Ausgang(Controller c) {
        this.c = c;
        new Thread(this).start();
    }

    public void run() {
        while (c.museumOffen() || c.getRausKehren()) {
                c.museumVerlassen();
        }
    }
}

public class Eingang implements Runnable {
    private Controller c;
    private int max = 50;

    public Eingang(Controller c) {
        this.c = c;
        new Thread(this).start();
    }

    public void run() {
        while (c.museumOffen()) {
            if (c.getCount() < max)
                c.museumBetretten();
        }
    }
}

public class Direktor implements Runnable {
    private Controller c;

    public Direktor(Controller c) {
        this.c = c;
        new Thread(this).start();
    }

    public void run() {
        try {
            c.museumWirdGeoeffnet();

            Thread.sleep(10);

            c.rausKehren();

            c.museumWirdGeschlossen();
        } catch (InterruptedException e) {
            e.getStackTrace();
        }

    }
}
 
wieso muss der Thread warten, wenn mehr als 50 User drin sind?

Wo wie wird der Thread wider aufgeweckt?
Wenn mehr als 50 drin sind ist halt kein Einlas mehr möglich. Erst wider wenn count kleiner als 50.
 
Zuletzt bearbeitet:
wieso muss der Thread warten, wenn mehr als 50 User drin sind?

Wo wie wird der Thread wider aufgeweckt?
Wenn mehr als 50 drin sind ist halt kein Einlas mehr möglich. Erst wider wenn count kleiner als 50.
Ja genau das ist meine Frage.

Ich mach das aus Eingang raus und versuche im Controller das ganze zu synchronisieren doch das klappt nicht.
 
beim Verlassen prüfst du den Counter beim Kommen nicht.


Baue doch mal zum testen eine WarteZeit in die run Methoden von Kommen und Verlassen ein damit du es besser beobachten kannst , und mache die Zeit vom Direktor auch länger.

Mache auch einer Textausgabe wenn das Warten im Controller ausgelöst wird und schaue wenn das Warten aufgehoben wird.
 
Zuletzt bearbeitet:
Interessant wenn ich sleep in Eingang und Ausgang mache, habe ich folgende Ausgabe:
Besucher 51 verlaesst das Museum
Besucher 51 betritt das Museum
Besucher 51 verlaesst das Museum
Besucher 51 betritt das Museum
Besucher 51 verlaesst das Museum
Besucher 51 betritt das Museum
Besucher 51 verlaesst das Museum
Besucher 51 betritt das Museum
Besucher 51 verlaesst das Museum
verstehen tue ich es nur leider überhaupt nicht gerade. Glaube ich schaue morgen nochmal drüber.
Möchte morgen auch noch versuchen das ganze dann mit Besuchern hin zu bekommen 🙂
 
Du hast ja drei versiedende Threads . Überlege welchen Thread du in welcher Methode zum warten schickst und wo du ihn wider aufweckst.

Tipp zum wider aufwecken mit notify brauchst du die Instanz der Threads den du wecken willst. Du kannst den Thread nur aus einem anderen wider starten. Nicht in sich selber.
 
Du hast ja drei versiedende Threads . Überlege welchen Thread du in welcher Methode zum warten schickst und wo du ihn wider aufweckst.

Tipp zum wider aufwecken mit notify brauchst du die Instanz der Threads den du wecken willst. Du kannst den Thread nur aus einem anderen wider starten. Nicht in sich selber.
Achso. Du meinst also ich soll den Eingang Thread schlafen legen sobald 50 Leute drin sind. Sobald wieder Leute raus gehen, weckt der Ausgang Thread den Eingang Thread so ungefähr oder?
 
Achso. Du meinst also ich soll den Eingang Thread schlafen legen sobald 50 Leute drin sind. Sobald wieder Leute raus gehen, weckt der Ausgang Thread den Eingang Thread so ungefähr oder?
nein einfach den Counter nicht mehr hoch zählen keinen mehr rein lassen. wenn einer raus geht kommt beim nächsten schleifen durchlauf wider einer rein.
 
Besucher 51 verlaesst das Museum
Besucher 51 betritt das Museum
Besucher 51 verlaesst das Museum
Besucher 51 betritt das Museum
Besucher 51 verlaesst das Museum
Besucher 51 betritt das Museum
Besucher 51 verlaesst das Museum
Besucher 51 betritt das Museum
einer geht einer kommt so soll es doch sein.
 
So sottest du ein asynchrones Verhalten beobachten können.

Java:
public class Controller {
    private boolean offen, rausKehren;
    private int count;

    public synchronized void museumWirdGeoeffnet() {
        System.out.println("Der Direktor oeffnet das Museum");
        offen = true;
    }

    public synchronized boolean getRausKehren() {
        return rausKehren;
    }

    public synchronized boolean museumOffen() {
        return offen;
    }

    public synchronized void museumWirdGeschlossen() {
        while(count > 0) {
            try {
                System.out.println("schliessen Warten");
                wait();
            }catch(InterruptedException e) {
                e.getStackTrace();
            }
        }
        rausKehren = false;
        System.out.println("Der Direktor schliesst das Museum");
    }

    public synchronized int getCount() {
        return count;
    }

    public synchronized void museumBetretten() {
        if (offen) {
            /*while (count > 50) {
                try {
                    System.out.println("betretten  Warten");
                    wait();

                } catch (InterruptedException e) {
                    e.getStackTrace();
                }
            }*/
            if(count<=50) {
                count++;
                System.out.println("Besucher " + count + " betritt das Museum");
            }
        }
    }

    public synchronized void museumVerlassen() {
        if (count > 0) {
            System.out.println("Besucher " + count + " verlaesst das Museum");
            count--;
        }

        notify();
    }

    public synchronized void rausKehren() {
        offen = false;
        rausKehren = true;
        notify();
    }

    public static void main(String[] args) {
        Controller c = new Controller();
        Direktor d = new Direktor(c);
        Eingang e = new Eingang(c);
        Ausgang a = new Ausgang(c);
    }

}

public class Eingang implements Runnable {
    private Controller c;
    private int max = 50;

    public Eingang(Controller c) {
        this.c = c;
        new Thread(this).start();
    }

    public void run() {
        while (c.museumOffen()) {
            if (c.getCount() < max)
                c.museumBetretten();
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}


public class Ausgang implements Runnable {
    private Controller c;

    public Ausgang(Controller c) {
        this.c = c;
        new Thread(this).start();
    }

    public void run() {
        while (c.museumOffen() || c.getRausKehren()) {
            try {
                Thread.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            c.museumVerlassen();
        }
    }
}


public class Direktor implements Runnable {
    private Controller c;

    public Direktor(Controller c) {
        this.c = c;
        new Thread(this).start();
    }

    public void run() {
        try {
            c.museumWirdGeoeffnet();

            Thread.sleep(500);

            c.rausKehren();

            c.museumWirdGeschlossen();
        } catch (InterruptedException e) {
            e.getStackTrace();
        }

    }
}
 
🤗🤗🤗 Jipi so sieht es doch super aus. Danke für eure tolle Mitarbeit und die super Hilfe 🙂

Eine Frage habe ich, gibt es eine Art "Grundregel" wann man while(...) oder if(...) in einem synchronized Block (Methode) nutzt?
Ich verstehe was da passiert doch alle Beispiele die ich sehe sind mit while(..). Dort muss dann der Thread wenn er ran kommt eben wieder Abfragen ob er überhaupt ran darf falls NEIN geht er eben wieder schlafen. Jetzt hätten wir aber ja if(..) somit fragt der Thread nur einmal. Mhhh... wenn Eingang z. B. aber dran ist, wissen wir ja das er zu ende laufen muss, selbst wenn ein Threadwechsel statt finden würde wäre Controller ja Blockiert durch synchronized. Damit wäre das while(...) überflüssig.

Kann man sagen das, wenn es eine Art Reihenfolge gibt ein if(..) ausreicht? Oder kann man das nie pauschal sagen?
 
while(...) ist eine Schleife die den Block solange widerholt wie der Ausdruck (Bedingung ) True ist.
if(...) bei If wird der Block nur einmal durchlaufen wenn die Bedingung True ist.

Das hat nichts mit synchronized Block zu tuen.

Bei syncronized kann halt immer nur ein Thread in die Methode rein die anderen müssen warten. Wer zuerst kommt mahlt zuerst der Rest muss warten.
 
Zuletzt bearbeitet:
while(...) ist eine Schleife die den Block solange widerholt wie der Ausdruck (Bedingung ) True ist.
if(...) bei If wird der Block nur einmal durchlaufen wenn die Bedingung True ist.
Das ist mir ja geläufig 😇
Nur habe ich eben bis jetzt nur while(..) gesehen und dachte das müsste man so immer machen.

Dann liegt es wohl an der Aufgabenstellung das man es so machen muss. Mensch ich tu mir hier so schwer als würde ich von Null anfangen zu Programmieren :-( Sry auch für die "doofen" Fragen dann meiner Seits :-D
 
Also ich habe ehrlich gesagt meine Probleme, Deine Implementation zu verstehen. Ich sehe keine Besucher. Was ist dieses Eingang für ein Thread? Also extrem dubios.

Was hier helfen würde, wäre eine genaue Beschreibung, was das für Elemente vorkommen und was diese machen.

Ist der Text der Aufgabe so komplett? Dann findet man da so diverse Aktöre:
  • Besucher - es gibt mehrere Besucher, die das Museum besuchen wollen.
  • Es gibt einen Museumsleiter, der irgendwas was macht oder dem etwas signalisiert wird.
  • u.s.w.

Und da habe ich dann doch ein paar Probleme, das wieder zu finden bei Dir und an Deinem Code kann ich das alles auch nicht wirklich ablesen.

Vielleicht hast Du ja mehr Informationen, als das, was Du uns gegeben hast, so dass Dein Ansatz Sinn ergibt.

Ich selbst hätte jetzt sowas gemacht wie:
jeder Besucher ist ein Thread. Dieser will das Museum besuchen und schaut daher:
  • Ist das Museum offen? Wenn nicht, dann hat sich das mit dem Besuch erledigt.
  • Dann betritt er das Museum. Wenn das Museum gerade voll ist, dann muss er warten.
  • Wenn er das Museum betreten hat, dann kann er das genießen. Das könnte dann auch wieder eine Art Warten sein.
  • Wenn er es genug besucht hast, dann verlässt er das Museum wieder
  • Und ganz wichtig: Es kann ihm gesagt werden: Das Museum schließt, gehen sie bitte. Dann würde das "warten" auch abgebrochen werden!

Du hast dann ein Museum / Controller / was auch immer. Das sorgt halt dafür, dass nie zu viele Besucher im Museum sind und so.

Du hast einen Museumsdirektor, der halt das Museum öffnet und dann später wieder schließt.

Die Besucher müssen generiert werden. Du kannst also einen Thread erstellen, der ständig Besucher-Threads erzeugt und startet.

Das wäre dann ggf. ein Vorgehen wie:
  • Museum wird erstellt, ist geschlossen.
  • Der Thread für die Besucher wird gestartet, dieser erzeugt jede 1/10 Sekunde einen Besucher. Diese bekommen dann eine Nummer.
  • Der Direktor wird gestartet, nach 5 Sekunden öffnet er das Museum, nach 30 Sekunden schließt er das Museum.

Mit den Besuchern passiert dann folgendes:
  • Die Besucher wollen dann das Museum besuchen, Museum ist geschlossen -> "Besucher 1: Museum geschlossen!"
  • irgendwann ist das Museum dann offen. Dann kommt etwas wie: "Besucher 50: Museum offen - betreten"
  • So die Besucher noch nicht das Museum verlassen haben, kommt dann irgendwann "Besucher: 100: Museum offen - in Warteschlange!"
  • Dann verlässt Besucher 50 das Museum ggf. wieder: "Besucher 50: Museum verlassen." so dass dann ein Besucher rein kann: "Besucher 100: Museum betreten."
  • ...

Das wäre dann etwas, das ich nachvollziehen kann und das ich da etwas erwarten würde. Aber wie gesagt: Dir liegen evtl. schlicht mehr Informationen vor und daher ist da tatsächlich etwas anderes zu bauen wie Du es da in Ansätzen hast. Aber irgendwie erscheint mir das gerade nicht wirklich alles so sinnbehaftet.
 
@KonradN GENAU DAS SELBE PROBLEM HATTE ICH GANZ ZU ANFANG VON DIESER AUFGABE!
Denn so wie du es beschreibst hätte ich es auch verstanden. Das ganze habe ich dann so unserem Tutor erklärt und er/sie meinte dann NÖ das ist viel viel zu weit gedacht. Nur so wie es da steht machen.

Den Ansatz mit den Besuchern hatte ich damals auch versucht zu implementieren und bin leider komplett gescheitert weil es viel zu komplex auf einmal wurde. Vielleicht bin ich aber wirklich dafür einfach zu "doof" oder denke um 1000 Ecken :-( so genau weiß ich das momentan noch nicht.

Nur läuft mir gerade auch etwas die Zeit davon um solche Aufgaben so ausführlich machen zu können. Deswegen, hört es sich jetzt nicht so gut an doch denke ich würde ich es hierbei belassen.

Vielleicht finde ich ja noch Zeit und werde dann deine tollen Ideen einarbeiten und daraus ein ebenfalls für mich sinnvolleres Programm bauen 🙂
Doch es gibt noch einiges was ich erledigen muss und ebenfalls stelle ich gerade fest überhaupt noch nicht verstanden habe. Selbst so Themen wie Petri-Netze oder bankier algorithmus fallen mir gerade nicht leicht. Es fehlt einfach die Übung. Vielleicht unterstützt ihr mich bei solchen Fragen ja ebenfalls 🙂

____
Was auch echt nett wäre bei diesem Museums Programm wäre eine mini GUI 🙂 Man baut einfach ein Haus und die Besucher z. B. als StrichMenschen. Diese wandern dann in das Haus (Museum) sind 50 drin kommt keiner mehr rein und anders laufen sie hinten eben wieder raus :-D Wäre ebenfalls eine Idee wie ich das später gerne mal versuchen würde.
 
Du hast ja die Theresas nur um das Drehkreuz am Eingang und Ausgang zu Simulieren.

Bei jeden Schleifen durchlauf der Threads dreht sich sozusagen das Kreutz.

Ps Wie wäre es wenn du die Aufgabe mal im Original zeigst.
 
Die Aufgabe:
A museum allows visitors to enter through the east entrance and exit through the
west exit. Arrival and departure are signaled to the museum manager through the
turnstiles at the entrance and exit. When the museum is open, the museum director
signals to the controller that the museum is open, and the controller then allows both
arrivals and departures. At the time of closure, the director signals that the museum
is closed. Now, the controller only allows departures.
There are at least four processes / monitors in this exercise: East, West, Control and
Director. Identify which of these should be threads and which should be monitors.
Provide a Java implementation of all classes and simulate a day in the museum
opening at 9:00 a.m. and closing at 4:00 p.m. Due to the current pandemic situation
take care that only 50 visitors may simultaneously enter the museum.
 
Ein Thread für Eingang und Ausgang zum Simulieren ist meiner Meinung richtig.

Ob es einen für den Direktor braucht fragwürdig nicht unbedingt.



Was du nicht hast ist eine Signalisierung das das Museum voll ist. Auch keine direkte sperre, für das Eingangs Kreutz. Also für den Thread, der das Kreutz darstellt. Das warten sollte eigentlich im dem Thread sein der ja den Besucher Strom simuliert.
 
Die englische Beschreibung ist ja auch eindeutig:
There are at least four processes / monitors in this exercise: East, West, Control and
Director

Und die Aufgabe hat ja auch schon einen ersten Schritt genannt:
Identify which of these should be threads and which should be monitors.

Ich würde halt generell dazu raten, immer erst als erstes genau zu formulieren, was denn die Aufgabe dann genau umfasst. Das ist immer ein wichtiger Schritt vor dem Start der Implementation.

East / West sind ja Eingang und Ausgang und Threads. Das wäre also schon beantwortet. Und wenn man sich den letzten Code von @Jw456 anschaut, dann hat man das auch für die beiden anderen Elemente beantwortet.

Dann bleibt nur noch die Frage, was denn diese Klasse genau machen sollen bzw. was die für eine Funktionalität haben sollen. Was soll genau passieren? Kannst Du das einmal im Detail beschreiben? Wenn das gewünschte Verhalten klar ist, dann kann man schauen, was notwendig ist, wenn man das jeweils implementiert. Dann wird auch klar, wo ggf. eine Schleife sein muss und wo eben keine Schleife sein darf.
 
🙄 oh weh ja da habe ich wohl euch nicht richtig erklärt was ich vor habe.

Also wie jetzt schon geschrieben wurde ist mein Eingang und Ausgang => East und West
Diese habe ich als Threads identifiziert, da sie die Besucher simulieren sollen die ja rein und raus aus dem Musem gehen können.

Der Direktor ist eigentlich nur aus Spaß ein Thread. Diesen könnte man auch als normale Klasse machen und dann eine Methode aufrufen die dann die Methoden im Controller aufruft und die Simulation beginnt.

Der Controller ist mein Monitor, dieser soll die Synchronisation der Threads sicherstellen so das es zu keinen inkonsistenzen kommt.

Das signalisieren dass das Museum zu ist fehlt oh ja. Könnte ich das alles nicht in der Methode betretteMuseum() erledigen. Diese habe ich nun so abgeändert.


Java:
public synchronized void museumBetretten() {
        if (offen) {
            if(count<50) {
                count++;
                System.out.println("Besucher " + count + " betritt das Museum");
            }
            else {
                System.out.println("Das Museum ist voll");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

Somit würde signalisiert werden das unser Museum jetzt voll ist. Dann legt sich wenn ich alles richtig verstehe, der Eingang schlafen. Irgendwann kommt der Ausgang wieder dran und ein Besucher verlässt das Museum. Diese Methode ruft notify() auf und weckt somit den Eingang Thread. Hab ja nur zwei Threads in der hin sich 🙂

Macht das Sinn? Ist es jetzt etwas besser erklärt?
 
nur weil count nicht kleiner als 50 ist muss es nicht voll sein, können ja auch esrst 10 im Museum sein.

grösser gleich als 50 würde sinn machen um anzuzeigen das es voll ist
 
Also wie jetzt schon geschrieben wurde ist mein Eingang und Ausgang => East und West
Diese habe ich als Threads identifiziert, da sie die Besucher simulieren sollen die ja rein und raus aus dem Musem gehen können.

Der Direktor ist eigentlich nur aus Spaß ein Thread. Diesen könnte man auch als normale Klasse machen und dann eine Methode aufrufen die dann die Methoden im Controller aufruft und die Simulation beginnt.
Wer sollte denn diese Methode vom Direktor aufrufen? Der Direktor muss also ein Thread sein.

Bei allen Deinen Ansätzen fehlt mir schlicht das Verständnis, was da überhaupt passieren soll. Ich kann bei deinen Code-Ansätzen nicht ablesen, was Du denn da genau machen willst.

Ein Besucher will in das Museum. Was kann dann passieren und wie reagiert man? Du musst das erst einmal in Worten beschreiben! Dann kann man das implementieren. Nur am Code rumbasteln ohne das, was passieren soll zu verstehen, wird nicht zum Ziel führen.
 
nur weil count nicht kleiner als 50 ist muss es nicht voll sein, können ja auch esrst 10 im Museum sein.
Okay, nur so ganz verstehen tu ich es nicht. Jetzt hab ich einfach ein else if(count >= 50) eingebaut. Doch was bringt mir das jetzt? Mehr Lesbarkeit?

@KonradN ich kann es leider nicht besser. Dachte mir was passiert als erstes? Naja der Direktor kommt und sagt so jetzt wird das Museum geöffnet. Das passiert dann über den Methodenaufruf c.museumWirdGeoeffnet(). Nun läuft unser Direktor munter durchs Museum (gedanklich) oder ruht sich irgendwo aus (keine Ahnung was so ein Museum Direktor alles erledigen muss). Nach einer gewissen Zeit gibt er bescheid, dass alle Leute raus müssen da unser Museum geschlossen wird. Dies erfolgt mit der Methode c.rausKehren(); Sobald alle Besucher draußen sind Sperrt er zu und geht nach Hause.

Sobald das Museum geöffnet wurde, bekommt der Eingang und Ausgang Bescheid. Im Eingang läuft dann bis das Museum geschlossen wird eine Methode c.museumBetretten(); Das heißt es dürfen Besucher durch das Drehkreuz (gedanklich) gehen um ins Museum zu gelangen. Es dürfen ja nicht mehr als 50 rein, somit wird nach 50 gesagt Stopp Museum ist voll.

Zugleich kann der Ausgang Thread an die Reihe kommen um Leute aus dem Museum zu schmeißen 😀 (also hier gehen eben gedanklich die Leute wieder raus) Soll das Museum geschlossen werden, werden vorher die restlichen Besucher rausgekehrt und dann das Museum geschlossen.

Ich kann es leider nicht besser. Bin ja froh das Ihr mir geholfen habt, das es derzeit überhaupt so schön läuft wie derzeit 😉
 
Natürlich kannst Du es auch besser - du verstehst nur noch nicht, was wir verlangen.

Du hast ein Museum und einen Thread Eingang, der Besucher in das Museum lässt.
Er ruft also eine Methode auf dem Museum auf, dass ein Besucher hinein will. Und wenn ein Besucher drin ist, dann ruft er es direkt wieder auf. Er packt also ständig Besucher in das Museum. Damit das erfolgreich funktioniert und die CPU nicht ausgelastet wird, muss der Thread sich immer, wenn nichts zu tun ist, schlafen legen.

Was kann es nun beim Museum für Fälle geben?
  • Es kann geschlossen sein. Was soll dann passieren?
  • Es kann geöffnet sein und es sind noch keine max Pesonen drin. Was dann?
  • Es kann geöffnet sein und es sind schon max Personen drin. Was dann?

Das musst musst Du jetzt spezifizieren - und zwar in Worten.
 
eigentlich brauchst du diese Begrenzung nicht das soll und tut ja dein Controller.
Der soll verbieten das weiter Besucher in das Museum können .
der soll anzeigen das voll ist der soll anzeigen das geschossen wurde ...

Das muss der simulierte Besucher Strom nicht machen.
Wird in Wirklichkeit auch nicht so sein. Die kommen und stellen sich an. Schauen auf die Anzeige. Museum offen, voll, der nächste bitte , Museum schließt bitte alle das Museum verlassen …

Java:
 while (c.museumOffen()) { // ist ok wenn Museum zu Thread wird beendet Besucher gehen wider nach Hause.
            if (c.getCount() < max) // nicht notwendig dein wait das sperren des Drehkreuz wird sonnst ja nicht ausgelöst.
                c.museumBetretten();
 
Zuletzt bearbeitet:
  • Es kann geschlossen sein. Was soll dann passieren?
  • Es kann geöffnet sein und es sind noch keine max Pesonen drin. Was dann?
  • Es kann geöffnet sein und es sind schon max Personen drin. Was dann?
Ist das Museum noch geschlossen, dachte ich das die Besucher dann vor der Tür stehen. Andernfalls könnte der Eingang dann eben Schlafen bis es geöffnet wird.

Wenn es offen ist und noch keine max. Personen drin sind, können die Besucher das Museum betretten.

Wenn es offen ist und schon max. Personen drin sind, kann der Eingang sich schlafen legen und warten bis irgendwann jemand raus geht.

Meinst du so in etwas?

if (c.getCount() < max) // nicht notwendig dein wait das sperren des Drehkreuz wird sonnst ja nicht ausgelöst.
Ja das hatte ich vorher schon raus genommen 🙂 Hier nur nicht gepostet das stimmt. Danke für den Hinweis ;-)
 
Andernfalls könnte der Eingang dann eben Schlafen bis es geöffnet wird.
Also kann dann der Thread sich schlafen legen -> Muss man dann im Hinterkopf behalten, denn beim Öffnen muss er dann geweckt werden!)

Meinst du so in etwas?
Ja genau. Das wäre dann der Ablauf, der in dem Controller umgesetzt werden muss.

Also hätten wir jetzt im Thread für den (einen) Eingang einfach nur ein
Java:
while (true) {
    museum.eintreten();
}

Und im eintreten hätte man dann ja an Logik:
  • Ist das Museum geschlossen? -> Schlafen legen!
  • Sonst: Ist das Museum bereits voll? -> Schlafen legen!
  • Sonst: Museum wird betreten.

Jetzt muss man noch überlegen, wo man die Schleife baut. Da würde aus meiner Sicht eine Schleife drum gehören, die verlassen wird, wenn man das Museum betreten hat.

Das wäre dann erst einmal der Code für das Eintreten (für jetzt!)



Jetzt musst Du Dir das beim Ausgang überlegen. Was passiert beim Ausgang? Was für Fälle gibt es da? Und was muss da gemacht werden?
 
Okay 🙂 Jetzt habe auch ich das verstanden.
Hab es mal umgesetzt. Auch beim Ausgang. Wäre ja doof wenn der Ausgang benutzt werden könnte wenn noch niemand da ist. Ist zwar nicht unbedingt notwendig doch es gibt mir ein besseres Gefühl 😀

Java:
package Aufgabe1;

public class Controller {
    private boolean offen, rausKehren;
    private int count;

    public synchronized void museumWirdGeoeffnet() {
        System.out.println("Der Direktor oeffnet das Museum");
        offen = true;
        notifyAll();
    }

    public synchronized boolean getRausKehren() {
        return rausKehren;
    }

    public synchronized boolean museumOffen() {
        return offen;
    }

    public synchronized void museumWirdGeschlossen() {
        while (count > 0) {
            try {
                System.out.println("schliessen Warten");
                wait();
            } catch (InterruptedException e) {
                e.getStackTrace();
            }
        }
        rausKehren = false;
        System.out.println("Der Direktor schliesst das Museum");
    }

    public synchronized void museumBetretten() {
        if (offen) {
            if (count < 50) {
                count++;
                System.out.println("Besucher " + count + " betritt das Museum");
            } else if (count >= 50) {
                System.out.println("Das Museum ist voll");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void museumVerlassen() {
        if (offen) {
            if (count > 0) {
                System.out.println("Besucher " + count + " verlaesst das Museum");
                count--;
            } else {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public synchronized void rausKehren() {
        offen = false;
        rausKehren = true;
        notifyAll();
    }

    public static void main(String[] args) {
        Controller c = new Controller();
        Direktor d = new Direktor(c);
        Eingang e = new Eingang(c);
        Ausgang a = new Ausgang(c);
    }

}

Was mich jetzt nur stört und vorher gar nicht aufgefallen ist, ist das es eine Reihenfolge gibt bzw. geben muss wie die Klassen aufgerufen werden müssen :-( Um das zu beheben würde mir aber nur einfallen das ich eine Art init-Methode im Controller hätte. Wir übergeben dem Controller den Direktor, Eingang und Ausgang. Diese init Methode sorgt dann dafür (oder auch der Konstruktor vom Controller) dass erst der Direktor los laufen darf und dann die anderen zwei 🙂
Was ich mich dabei jetzt aber wieder frage ist, was ist wenn viel Last auf einem System ist. Der Controller dann die Klassen initialisiert und der Direktor so gesehen gar nicht die run-Methode ausführen kann, ein Threadwechsel statt findet. Dann könnte z. B. der Eingang die run-Methode ausführen und beendet die while Schleife auf der Stelle da der Direktor das Museum nicht aufgemacht hat. 🤨 Das finde ich gerade echt Problematisch.
Werde es mal umbauen und schauen ob es dann noch läuft wie ich es mir vorstelle, löst nur das Problem nicht gänzlich oder?
 
Also ich bekomme es leider nicht hin erst dann zu starten wenn Direktor wirklich gestartet ist.
Java:
Controller c = new Controller();
        Direktor d = new Direktor(c);
        //Hier pruefen ob Direktor run Ausführt
        Eingang e = new Eingang(c);
        Ausgang a = new Ausgang(c);

Code:
public class Direktor implements Runnable {
    private Controller c;
    private boolean running = false;

    public Direktor(Controller c) {
        this.c = c;
            new Thread(this).start();
    }

    public void run() {
        try {
            running = true;
            c.museumWirdGeoeffnet();

            Thread.sleep(500);

            c.rausKehren();

            c.museumWirdGeschlossen();
        } catch (InterruptedException e) {
            e.getStackTrace();
        } finally {
            running = false;
        }

    }

    public boolean isRunning() {
        return running;
    }
}

Ist es aber so gesehen dann nicht reiner Zufall das es läuft?
 
Dann starte doch die beiden entweder im Konstruktor oder im der run vom Direktor.

Wie schaust denn deine run, while Schleife in deinem Eingang und Ausgang jetzt aus?
 
Zuletzt bearbeitet:
Java:
 public synchronized void museumVerlassen() {
        if (offen) {
            if (count > 0) {
                System.out.println("Besucher " + count + " verlaesst das Museum");
                count--;
            } else {
                try {
                    wait(); // das müsste doch ein else vom ersten if sein also offen.
// du willst doch warten das Kreutz sperren wenn das Museum zu ist.

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
 
Ich hab das mit dem wait() bei museumVerlassen ganz raus geworfen. Dann ging es nicht mehr, hatte endlosschleife. Ich mach wohl irgendwo ein notiryAll() falsch :-(

Hier jetzt nochmal alles. Ob es nun bis auf das mit dem mueseumVerlassen aber wirklich richtig läuft weiß ich nicht. Denn ich weiß nicht wie die JVM die Threads behandelt. Ich starte ja nun im Konstruktor alle Threads doch irgendwie habe ich das Gefühl das sich nichts geändert hat oder irre ich mich.

Java:
public class Controller {
    private boolean offen, rausKehren;
    private int count;

    public synchronized void museumWirdGeoeffnet() {
        System.out.println("Der Direktor oeffnet das Museum");
        offen = true;
        notifyAll();
    }

    public synchronized boolean getRausKehren() {
        return rausKehren;
    }

    public synchronized boolean museumOffen() {
        return offen;
    }

    public synchronized void museumWirdGeschlossen() {
        while (count > 0) {
            try {
                System.out.println("schliessen Warten");
                wait();
            } catch (InterruptedException e) {
                e.getStackTrace();
            }
        }
        rausKehren = false;
        System.out.println("Der Direktor schliesst das Museum");
    }

    public synchronized void museumBetretten() {
        if (offen) {
            if (count < 50) {
                count++;
                System.out.println("Besucher " + count + " betritt das Museum");
            } else if (count >= 50) {
                System.out.println("Das Museum ist voll");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void museumVerlassen() {
        if (offen) {
            if (count > 0) {
                System.out.println("Besucher " + count + " verlaesst das Museum");
                count--;
            }
        }
    }

    public synchronized void rausKehren() {
        offen = false;
        rausKehren = true;
        notifyAll();
    }

    public static void main(String[] args) {
        Controller c = new Controller();
        Direktor d = new Direktor(c, new Eingang(c), new Ausgang(c));

    }
}

public class Direktor implements Runnable {
    private Controller c;
    private Eingang eingang;
    private Ausgang ausgang;

    public Direktor(Controller c, Eingang eingang, Ausgang ausgang) {
        this.c = c;
        this.ausgang = ausgang;
        this.eingang = eingang;
        new Thread(this).start();
        new Thread(eingang).start();
        new Thread(ausgang).start();
    }

    public void run() {
        try {           
            c.museumWirdGeoeffnet();

            Thread.sleep(500);

            c.rausKehren();

            c.museumWirdGeschlossen();
        } catch (InterruptedException e) {
            e.getStackTrace();
        }

    }

}
 
beim Verlassen musst du immer ein notify machen denn du willst ja das eventuelle gesperrte Kreutz freigeben.
das hattes du ja im anfangs code auch.
 
beim Verlassen musst du immer ein notify machen denn du willst ja das eventuelle gesperrte Kreutz freigeben.
das hattes du ja im anfangs code auch.
Stimmt. Damit kann ich dann auch alles von notifyAll zu notify ändern. So gesehen kann ja dann immer nur der Eingang sich schlafen legen 🙂

Öhhh... ich hab den Direktor jetzt so geändert:
Java:
public class Direktor implements Runnable {
    private Controller c;
    private Eingang eingang;
    private Ausgang ausgang;

    public Direktor(Controller c, Eingang eingang, Ausgang ausgang) {
        this.c = c;
        this.ausgang = ausgang;
        this.eingang = eingang;
        new Thread(this).start();
    }

    public void run() {
        try {
            c.museumWirdGeoeffnet();
            if (c.museumOffen()) {
                new Thread(eingang).start();
                new Thread(ausgang).start();
            }
            Thread.sleep(500);

            c.rausKehren();

            c.museumWirdGeschlossen();
        } catch (InterruptedException e) {
            e.getStackTrace();
        }

    }

}

Wenn das Museum dann eben nicht offen ist bzw. Eingang und Ausgang noch nicht durch sind passiert eben nix. Man bekommt die Ausgabe Museum offen und Museum geschlossen fertig 😀 Dann hat das Museum keine Besucher an diesem Tag :-D

Könnte man dort nicht auch irgendwie durch eine Exception das ganze hin bekommen? Man wirft eine Exception und in der Fehlerbehandlung starten wir die Threads und dann sollte es auch laufen oder 🙃
 
Java:
public class Direktor implements Runnable {
    private Controller c;
  
    public Direktor(Controller c) {
        this.c = c;
        new Thread(this).start();
    }

    public void run() {
        try {
            
            c.museumWirdGeoeffnet();

            Eingang e = new Eingang(c);
            Ausgang a = new Ausgang(c);

            Thread.sleep(500);

            c.rausKehren();

            c.museumWirdGeschlossen();
        } catch (InterruptedException e) {
            e.getStackTrace();
        }

    }

    
}
 
Super Danke 🙂 Jetzt scheint es zu laufen. Zumindest hab ich es jetzt ca. 50x ausprobiert.
Auf die Simple Idee wie oben bin ich mal wieder nicht gekommen grrr...
Jetzt finde ich es sehr gut gelungen.
 
in der main mit deinem running Flag etwa so
Java:
Controller c = new Controller();
        Direktor d = new Direktor(c);

        while (!d.isRunning()) {                 }
        System.out.println("Direktor is Running");
        Eingang e = new Eingang(c);
        Ausgang a = new Ausgang(c);
 
Zuletzt bearbeitet:

Zurück
Oben