Threads Counter mit ungeraden Zahlen

BodyLAB

Bekanntes Mitglied
Hallo,

habe zwei Fragen zu einem Code.
1. Warum werden nicht nur ungerade Zahlen ausgegeben?
2. Der Quellcode soll so Synchronisiert werden das nur ungerade Zahlen ausgegeben werden ohne eine weiter Variabele oder die main Methode zu ändern.

Java:
package Aufgabe2;

public class Counter extends Thread {
    static Integer counter = 0;

    public void run() {
        while (counter < 1000) {
                increment();
                System.out.println(counter);
                increment();
        }
    }

    private void increment() {
        counter++;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++)
            new Counter().start();
    }

}

Zu 1. Es werden deswegen nicht nur ungerade Zahlen ausgegeben weil die Threads um das Objekt counter konkurrieren. Sie greifen alle auf das Objekt zu und verändern es. Somit ist immer unklar welcher Wert in counter steckt. Dazu kommt das System.out.println gepuffert wird und man nicht genau sagen kann wann die Ausgabe erfolgt und wann eben das Objekt erneut geändert wurde.

Kann man das verstehen und wäre das ansatzweise Korrekt?

Zu 2.
Hier bin ich gescheitert und glaube das ich synchronized nicht verstehe :-(
Java:
package Aufgabe2;

public class Counter extends Thread {
    static Integer counter = 0;
    
    public Counter(String n) {
        super(n);
    }

    public void run() {
        while (counter < 1000) {
        synchronized (this) {
                System.out.print("Name: " + this.getName() + " ");
                increment();
                System.out.println(counter);
                increment();
            }
        }
    }

    private void increment() {
        counter++;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++)
            new Counter("" + i).start();
    }

}

Das war meine Idee. Leider ohne Erfolg. Bin davon ausgegangen das synchronized für das Objekt Counter mit der instanz 0 z. B. dann blockiert und erst diese instanz fertig laufen darf. Das scheint wohl nicht so zu sein oder? Das wäre jedoch sehr merkwürdig da man dann ja nie eine Klasse die Synchronisiert ist mit mehreren instanzen synchron laufen lassen dürft! Deswegen muss meine Annahme wohl falsch sein. Wo dann der Fehler steckt weiß ich nicht. Der aller erste Ansatz war die increment Methode mit synchronized auszustatten (ging auch nicht).

Danke vorab :)
 

LimDul

Top Contributor
Also, die Idee mit synchronized ist schon gut. Du gibst bei synchronized an, welches Objekt quasi der Lock ist. Und von dem Objekt kann immer nur ein Thread gleichzeitig den Lock haben.

Jetzt schauen wir uns mal, welche Objekte du erstellst und welche Locks die verwenden:

Du erstellst fünf Objekte vom Typ Counter - nennen wir die mal passend counter0 bis counter4.

Welches Objekt verwendet counter0 als Lock? Nun this - was counter0 entspricht.
Welches Objekt verwendet counter1 als Lock? Nun this - was counter1 entspricht.
Sprich jedes Objekt verwendet seinen eigenen Lock und synchronziert sich damit nur mit sich selber. Was wie du festgestellt hast, recht witzlos ist.

Du musst also ein Objekt beim synchronized verwenden, dass in allen Objekten verwendet wird. Die erste Idee wäre, counter zu verwenden - das ist ja static, aber das wird leider auch nicht funktionieren, da counter++ in wirklichkeit ein neues counter Objekt erzeugt. (Autoboxing / Unboxing lässt grüßen).

Das heißt, leg einfach ein neues Objekt in main an - z.B. per Object sharedLock = new Object(); und übergib das (und zwar allen das gleiche) deinen Counter-Klassen und verwende das im synchronized-Block.
 

BodyLAB

Bekanntes Mitglied
Hallo,
ja so ist es zumindest synchronisiert. Was mich nur wundert ist die Aufgabe, denn dort steht ja folgendes:
Synchronisieren Sie den Quellcode, so dass nur ungerade Zahlen ausgegeben werden. Fügen Sie der Klasse keine weiteren Variablen hinzu und verändern Sie auch nicht die main() Methode.

Doch hier würde ich ja eine weiteres Datenelement hinzufügen und die main-Metehode ändern.
Fügen Sie der Klasse keine weiteren Vaiablen hinzu => sind doch Datenelemente gemeint oder 🙃
Verändern Sie auch nicht die main Methode => also sicher die gesamte Main Methode.

Doch wie soll es anders gehen. So dreht man sich doch nur im Kreis oder :eek:
Java:
public class Counter extends Thread {
    static Integer counter = 0;
    private Object lock;
   
    public Counter(String n, Object lock) {
        super(n);
        this.lock = lock;
    }

    public void run() {
       
        while (counter < 1000) {
            synchronized (lock) {
                System.out.print("Name: " + this.getName() + " ");
                increment();
                System.out.println(counter);
                increment();
            }
        }
    }

    private void increment() {
        counter++;
    }

    public static void main(String[] args) {
        Object lock = new Object();
        for (int i = 0; i < 5; i++)
            new Counter("" + i, lock).start();
    }

}


______
Welches Objekt ist den nun der Monitor wenn die run Methode synchronized ist? Also so:
Java:
public synchronized void run() { ... }
Wer wäre in diesem Falle der Monitor? Counter oder Thread
 
Zuletzt bearbeitet:

Jw456

Top Contributor
Dann solltet du deinen counter
auch prüfen ob er gerade oder ungerade ist und nur bei gerade das print aufrufen.
Tipp modulo könnte helfen um auf gerade oder ungerade zu prüfen
 

BodyLAB

Bekanntes Mitglied
Dann solltet du deinen counter
auch prüfen ober gerade oder ungerade ist und nur bei gerade das print aufrufen.
Tipp modulo könnte helfen um auf gerade oder ungerade zu prüfen
Das hatte ich schon. Dort ist das Problem dass dann erneut Daten verloren gehen. Da ja immer mal wieder die anderen Threads in die Quere kommen und man in der if() Abfrage unterbrochen werden kann etc.
Denn ich bekomme dann nur misst raus.

Java:
public class Counter extends Thread {
    static Integer counter = 0;
  
    public Counter(String n) {
        super(n);
    }

    public void run() {
      
        while (counter < 1000) {
          
                System.out.print("Name: " + this.getName() + " ");
                increment();
            if(counter % 2 == 1)
                System.out.println(counter);
                increment();
          
        }
    }

    private void increment() {
        counter++;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++)
            new Counter("" + i).start();
    }

}

Ausgabe:
Name: 1 Name: 4 Name: 4 Name: 3 Name: 4 Name: 3 Name: 3 Name: 2 Name: 0 Name: 2 Name: 0 Name: 3 Name: 4 1
Name: 4 27
Name: 3 Name: 0 29
Name: 3 33
Name: 3 35
Name: 3 37
Name: 3 39
Name: 3 41
Name: 3 43
Name: 3 45
Name: 3 47
Name: 3 49
Name: 3 51
Name: 3 53
Name: 3 55
Name: 3 Name: 2 57
Name: 3 61
Name: 3 63
Name: 3 65
Name: 3 67
Name: 3 69
Name: 3 71
Name: 3 73
Name: 3 75
Name: 3 77
Name: 3 79
Name: 3 81
Name: 3 83
Name: 3 85
Name: 3 87
Name: 3 89
Name: 3 91
Name: 3 93
Name: 3 95
Name: 3 97
Name: 3 99
Name: 3 101
Name: 3 103
Name: 3 105
Name: 3 107
Name: 3 109
Name: 3 111
Name: 3 113
Name: 3 115
Name: 3 117
Name: 3 119
Name: 3 121
Name: 3 123
Name: 3 125
Name: 3 127
Name: 3 129
Name: 3 131
Name: 3 133
Name: 3 135
Name: 3 137
Name: 3 139
Name: 3 141
Name: 0 143
Name: 4 Name: 1 Name: 3 Name: 0 145
Name: 2 Name: 4 Name: 0 Name: 3 Name: 1 Name: 3 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 4 Name: 4 Name: 4 153
Name: 4 181
Name: 0 Name: 4 Name: 4 Name: 3 Name: 1 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 183
Name: 2 Name: 0 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 3 Name: 1 Name: 3 Name: 3 Name: 3 Name: 4 Name: 4 Name: 0 207
Name: 0 249
Name: 0 251
Name: 0 253
Name: 0 Name: 4 Name: 3 Name: 1 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 4 Name: 4 Name: 4 255
Name: 2 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 4 Name: 4 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 1 Name: 1 Name: 1 Name: 1 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 3 Name: 0 Name: 4 Name: 4 Name: 4 Name: 4 301
Name: 2 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 4 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 0 Name: 3 Name: 1 Name: 4 929
Vielleicht ist das aber ja gewollt hehe
 

BodyLAB

Bekanntes Mitglied
Die Main Methode muss ich nicht mehr ändern. Doch es wird ein Datenelement zur Klasse hinzugefügt. Glaube das geht gar nicht anders.
Java:
public class Counter extends Thread {
    static Integer counter = 0;
    private static final Object monitor = new Object();

    public Counter(String n) {
        super(n);
    }

    public void run() {

        while (counter < 1000) {
            synchronized(monitor) {
                System.out.print("Name: " + this.getName() + " ");
                increment();
                System.out.println(counter);
                increment();
            }
        }
    }

    private void increment() {
        counter++;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++)
            new Counter("" + i).start();
    }

}
 

BodyLAB

Bekanntes Mitglied
Kann mir noch jemand erklären was das hier bedeutet? Also welches Objekt wird hier als Monitor verwendet?

Java:
class TestThread extends Thread {
    private int i = 0;
    
    public synchronized void run() {
        while(true) i++;
    }
}

Was bedeutet es wenn man die run Methode synchronized macht.
 

httpdigest

Top Contributor
welches Objekt wird hier als Monitor verwendet?
Da das synchronized Schlüsselwort an einer Instanzmethode geschrieben wurde, ist der Monitor immer das Objekt, auf dem du die Methode aufrufst.
In deinem Fall wirst du aber vermutlich die run-Methode nicht direkt aufrufen, sondern der Thread, den du da startest, ruft die Methode auf.
Nichtsdestotrotz ist der Monitor die TestThread-Instanz, die du startest - intern ruft der dadurch neu erzeugte Thread ja die run() Methode auf der TestThread-Instanz auf.
Was bedeutet es wenn man die run Methode synchronized macht.
Dasselbe, was es bedeutet, wenn du jede andere Methode synchronized machst: Dass nur ein Thread zur Zeit die Methode aufrufen kann. Und in diesem Fall wird es halt der Thread sein, der durch die TestThread Instanz repräsentiert wird.
 

shokwave

Mitglied
Die Main Methode muss ich nicht mehr ändern. Doch es wird ein Datenelement zur Klasse hinzugefügt. Glaube das geht gar nicht anders.
Naja, in der Aufgabe steht, dass man keine neue Variable hinzufügen soll. Da steht aber nicht, dass man die vorhandene nicht ändern darf.
Meine Idee wäre, eine Klasse zu bauen, die ein Integer verwaltet(erhöht und zurück gibt) und dann "counter" ein Objekt dieser Klasse werden zu lassen. Dann kann der "counter" der Monitor sein.
Oder hab ich was übersehen?
 

Jw456

Top Contributor
Limdul hat dir die Fage eigentlich schon beantwortet. Was musst du synconisiren? Nicht die run Methode.
Auf welche variable darf immer nur einer zugreifen.
Wieviel instanzen von der counter variablen giebt es?
Das sind Fragen die dur dir stellen solltest.
 

BodyLAB

Bekanntes Mitglied
Limdul hat dir die Fage eigentlich schon beantwortet.
Das habe ich doch auch so Programmiert und es geht. Nur steht in der Aufgabe leider das man keine neue Variable hinzufügen darf oder die Main Methode ändern darf. Das musste ich aber leider bei dieser Lösung. Zumindest muss ja eine Variable hinzugefügt werden z. B.
Java:
    private static final Object monitor = new Object();

Tipp versuche es doch mal mit einer static counter Variablen.
Oh sekunde gute Idee :cool:
 

BodyLAB

Bekanntes Mitglied
Nein leider geht es nicht.
Java:
public class Counter extends Thread {
    static Integer counter = 0;
    //private static final Object monitor = new Object();

    public Counter(String n) {
        super(n);
    }

    public void run() {
        while (counter < 1000) {
            synchronized(counter) { //synchronized(monitor) { geht (doch es ist eine Variable dazugekommen)
                System.out.print("Name: " + this.getName() + " ");
                increment();
                System.out.println(counter);
                increment();
            }
        }
    }

    private void increment() {
        counter++;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++)
            new Counter("" + i).start();
    }
}

Ahha okay das geht leider ebenfalls nicht, da

Synchronization should not be done on instances of value-based classes​

Java:
Noncompliant Code Example

private static final Boolean bLock = Boolean.FALSE;
private static final Integer iLock = Integer.valueOf(0);
private static final String sLock = "LOCK";
private static final List<String> listLock = List.of("a", "b", "c", "d");

public void doSomething() {

  synchronized(bLock) {  // Noncompliant
    // ...
  }
  synchronized(iLock) {  // Noncompliant
    // ...
  }
  synchronized(sLock) {  // Noncompliant
    // ...
  }
  synchronized(listLock) {  // Noncompliant
    // ...
  }
 

BodyLAB

Bekanntes Mitglied
Deswegen meine Idee, mit der eigenen Klasse, für die "counter" Variable.
Ja das geht ;-)
Doch auf die Idee wäre ich so nie gekommen!
:(

So würde es wohl laufen:
Java:
public class Counter extends Thread {
    static IntValue counter = new IntValue(0);
    
    public Counter(String n) {
        super(n);
    }

    public void run() {
        while (counter.getValue() < 1000) {
            synchronized(counter) {
                System.out.print("Name: " + this.getName() + " ");
                counter.increment();
                System.out.println(counter.getValue());
                counter.increment();
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++)
            new Counter("" + i).start();
    }
}

public class IntValue {
    static int value;
    
    public IntValue(int value) {
        this.value = value;
    }
    
    public void increment() {
        value++;
    }
    
    public int getValue() {
        return value;
    }
    
}
 

httpdigest

Top Contributor
Eine weitere Idee wäre, auf dem Class Objekt der Klasse Counter zu synchronisieren, also:
Java:
public void run() {
  while (counter < 10000) {
    synchronized (Counter.class) {
      increment();
      System.out.println(counter);
      increment();
    }
  }
}
Das erfordert keinerlei zusätzliche Variablen. Der Trick ist nur, zu wissen, dass es solch ein Class-Objekt gibt.
 

BodyLAB

Bekanntes Mitglied
Das hilft mir alles ungemein Danke
Eine weitere Idee wäre, auf dem Class Objekt der Klasse Counter zu synchronisieren, also:
Okay das läuft ebenfalls. Doch das hier verstehe ich leider überhaupt nicht sry.

Vorher bei static Datenelement (Objekt) ist dieses Objekt ja schon vorher da und wir sperren dieses über die Referenz und geben es erneut frei.
Bei der Lösung oben von @LimDul erstellen wir ein Objekt und geben dieses dem Konstruktor mit. Speichern die Referenz im jeweiligen Objekt und sperren dann durch die Referenz das Objekt, das in der Main erstellt wurde.

Doch was passiert bei Counter.class da komme ich jetzt überhaupt nicht mehr mit!
 

httpdigest

Top Contributor
Doch was passiert bei Counter.class da komme ich jetzt überhaupt nicht mehr mit!
Der Ausdruck Counter.class wertet zu einem Objekt des Typs java.lang.Class aus und meint "diese Klasse" (als Objekt). Der hier verwendete Monitor ist letztlich exakt derselbe wie bei statischen Methoden dieser Klasse mit dem Schlüsselwort synchronized.
Also:
Java:
public static synchronized void methode() {...}
ist vom Verhalten her dasselbe wie:
Java:
public static void methode() {
  synchronized (Counter.class) {
    ...
  }
}
Du hast bei dir nur keine statische Methode und deswegen kannst du ein synchronized-Block mit dem Class-Objekt verwenden.
 

Jw456

Top Contributor
Java:
 synchronized static Integer counter = 0;
Sollte es sein. Somit kann imner nur einer auf die wapper Klasse zugreifen.
Und da es static ist gibt es sie auch nur einmal.
 

httpdigest

Top Contributor
Java:
 synchronized static Integer counter = 0;
Sollte es sein. Somit kann imner nur einer auf die wapper Klasse zugreifen.
Und da es static ist gibt es sie auch nur einmal.
Nein. Siehe: https://www.java-forum.org/thema/counter-mit-ungeraden-zahlen.198543/#post-1318916
Du musst also ein Objekt beim synchronized verwenden, das in allen Objekten verwendet wird. Die erste Idee wäre, counter zu verwenden - das ist ja static, aber das wird leider auch nicht funktionieren, da counter++ in wirklichkeit ein neues counter Objekt erzeugt. (Autoboxing / Unboxing lässt grüßen).
 

httpdigest

Top Contributor
Die counter Variable ist doch von Anfang an static. Es sollte also in allen 5 Threads die gleiche Instanz benutz werden. Auch nur eine geben auch wenn es mehrerer Objekte von der Klasse gibt.
Ja, am Anfang, bis der erste Thread counter++ ausführt. Ab dann machen alle Threads, was sie wollen, weil sie im Zweifel alle auf unterschiedliche Objekte synchronisieren für die nächsten Iterationen. Und, darüber hinaus hast du ja auch keine Garantie, dass alle Threads immer exakt gleichzeitig an jedem synchronized-Punkt pro Iteration ankommen.
Also: Du hast ja überhaupt keine Garantie, dass jeder Thread zu jedem Zeitpunkt immer dasselbe Objekt in der Variablen sieht. Dazu müsste die Variable auch noch final sein, was sie aber nicht ist.
 

KonradN

Super-Moderator
Mitarbeiter
Oder ein static synchronized getter von counter. Der dann benutzt wird.
Es nützt Dir doch nichts, den Getter zu synchronisieren. Dann kann nur ein Thread auf einmal den Getter Aufrufen, aber das machen 2 Threads hintereinander und beide addieren 1 ... und schreiben es zurück und damit ist dann von den 2 Mal erhöhen nur eins erfolgt.
 

BodyLAB

Bekanntes Mitglied
Dieser Gesprächs-Thread hier ist ein perfektes Beispiel dafür, wie unfassbar schwer doch Multithreading mit Shared Memory tatsächlich ist, und wie schnell es unterschätzt wird bzw. wichtige Dinge übersehen werden können.
Danke. Genau so ist es, ich sortiere das ganze später mal ein und schau ob ich es wirklich richtig verstehe :)

Noch etwas anders. Hat jemand ein Ansatz für dieses Problem?
Gegeben ist folgende Klasse:
Java:
public class Lager extends Thread {
    private boolean vorhanden = false;
    private int paket;

    public synchronized int abholen() {
        if (vorhanden == true) {
            vorhanden = false;
            return paket;
        }
        
    }

    public synchronized void anliefern(int wert) {
        if (vorhanden == false) {
            vorhanden = true;
            paket = wert;
        }
    }
}

Bei dieser Implementierung von Lager gibt es das Problem, dass die Operation abholen() keinen Rückgabewert liefert, wenn kein Paket vorhanden ist und deshalb nicht übersetzt werden kann. Notwendig wäre, dass abholen() wartet, bis ein Paket angeliefert wird. Genauso schreibt anliefern() nur dann den übergebenen Wert in paket , wenn kein Paket vorhanden ist. Geben Sie modifizierte Versionen von abholen() und anliefern() an, so dass die Operationen anstelle der if Abfrage warten, bis sie durchgeführt werden können, keine Verklemmung auftreten kann und der Zugriff auf das Paket wechselseitig ausgeschlossen ist.
Mein erster gedanke war wieder mal simple doch das kann überhaupt nicht sein. Ich dachte bei dieser Aufgabe auf der Stelle an ein Erzeuger und Verbraucher System. Doch die Klasse Lager ist ebenfalls ein Thread und das verwirrt mich. Wenn es ein Erzeuger Verbraucher System wäre, könnte man ja das Lager als Buffer aufbauen also so:
Java:
public class Buffer {

    private boolean available = false;
    private int data;

    public synchronized void put(int x) {
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        data = x;
        available = true;
        notifyAll();
    }

    public synchronized int get() {
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        available = false;
        notifyAll();
        return data;
    }
}

Das kann ja aber nicht sein weil Lager eben ein Thread sein soll und die run-Methode implementieren sollte dann. Somit müsste man das Lager ja schlafen legen und wer macht es wieder wach?
Wenn nicht erstelle ich dazu auch gerne erst mal ein eigenes Thema ;-)
 

KonradN

Super-Moderator
Mitarbeiter
Mein erster gedanke war wieder mal simple
Und das sieht doch auch gut aus. Ich denke, der Gedanke war prinzipiell schon goldrichtig. Nun bau es nur eben in die Methoden von Lager ein, denn das it ja die Aufgabe.

Das kann ja aber nicht sein weil Lager eben ein Thread sein soll und die run-Methode implementieren sollte dann.
Nein, Das extends Thread würde ich hier ehrlich gesagt nicht beachten. Es gibt keine run Methode und für die Funktionalität braucht es auch eine run Methode.

Wer oder was startet denn den Thread?
Wer ruft die beiten Methoden auf?
Das spielt doch für die Aufgabe keine Rolle. Es ist doch klar, was die Methoden machen sollen durch den vorhandenen Code und die Aufgabe.
 

BodyLAB

Bekanntes Mitglied
Gut dann hätte ich nun zwei Lösungen. Ich dachte daran, was ist wenn es eine run Methode gibt. Wie müsste die dann aussehen um auf die Lösung der Aufgabe zu kommen. Das war dann wohl doch wieder um zu viele Ecken gedacht.

Also der erste Lösungsansatz wäre das extends Thread eben mehr oder weniger einfach zu vernachlässigen:
Java:
public class Lager extends Thread {
    private boolean vorhanden = false;
    private int paket;

    public synchronized int abholen() {
        while (!vorhanden) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        vorhanden = false;
        notifyAll();
        return paket;
    }
    
    public synchronized void anliefern(int wert) {
        while (vorhanden) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        paket = wert;
        vorhanden = true;
        notifyAll();
    }
}

Der zweite Ansatz wäre es eben als Erzeuger-Verbraucher System zu Modellieren (das dürfte aber wahrscheinlich gegen die Aufgabe verstoßen da dort ja nicht steht das die Klasse verändert werden darf (es sollen ja nur die zwei Methoden verändert werden)):
Java:
public class Lager2 extends Thread {

    private Buffer b;

    Lager2(Buffer b) {
        this.b = b;
    }

    public void anliefern(int wert) {
        b.put(wert);
    }

    public int abholen() {
        return b.get();
    }

}

Die Klasse Buffer ist die selbe wie oben die :cool:
 

KonradN

Super-Moderator
Mitarbeiter
Ja, das Erste wäre auch, was ich als Lösung hier ansehen würde. Ein spezieller Thread ist hier nicht notwendig und eine zusätzliche run Methode wäre vermutlich auch nicht im Sinne der Aufgabe, die ja nur die Anpassung dieser beiden Methoden vorsieht:
Geben Sie modifizierte Versionen von abholen() und anliefern() an
 

BodyLAB

Bekanntes Mitglied
Wer oder was startet denn den Thread?
Wer ruft die beiten Methoden auf?
Das verunsichert mich jetzt aber etwas.

Vielleicht gibt es noch eine weiter Lösung.
____
Ich hab nun mal zwei Klassen erstellt eine Producer und Consumer Klasse. Dort übergebe ich das von oben erstellte Lager und es klappt wie aus dem Lehrbuch.
Nun habe ich mich weiter gefragt, ist das extends Thread in der Lager Klasse nur Verwirrung oder vielleicht macht es auch anders Sinn.
So gesehen wäre Lager doch Producer und Consumer in einem wenn dort eine run Methode existieren würde. Gibt es ein solches "design pattern" in der Parallelen Entwicklung?

😵‍💫😵‍💫😵‍💫
 

KonradN

Super-Moderator
Mitarbeiter
Lass Dich einfach nicht verunsichern!

Ich hab nun mal zwei Klassen erstellt eine Producer und Consumer Klasse. Dort übergebe ich das von oben erstellte Lager und es klappt wie aus dem Lehrbuch.
Damit hast Du Deine Lösung sozusagen mit Hilfe eines Tests bestätigt. Das ist doch erst einmal eine super Sache!

Und bezüglich des extends Thread: hat das irgend eine Relevanz für die Aufgabe? Haben synchronized, wait und notify ein besonderes Verhalten, wenn diese in einer Instanz aufgerufen werden, die von Thread erbt? Thread könnte z.B. wait und notifyAll überschrieben haben. Aber Du hast es ja getestet - und da es funktioniert hat, scheint da nicht wirklich etwas zu sein, oder?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
H Counter durch gepresste Taste nur auf 1 erhöhen und nicht durchzählen lassen Java Basics - Anfänger-Themen 7
Ostkreuz Counter für Booleanwerte Java Basics - Anfänger-Themen 8
P Iterieren mit einer Foreach in Lambdaschreibweise und Counter. Java Basics - Anfänger-Themen 1
S Counter Label Button Java Basics - Anfänger-Themen 4
P Counter im Konstruktor Java Basics - Anfänger-Themen 11
S Java Counter: nur 1 mal hochzählen auch wenn Abfrage mehrmals zutrifft. Java Basics - Anfänger-Themen 1
I counter der ausgegebenen zahlen Java Basics - Anfänger-Themen 2
Todesbote Treeset - Wenn bestimmtes Objekt vorkommt Counter erhöhen Java Basics - Anfänger-Themen 6
CR7 String schneiden und Counter hochzählen Java Basics - Anfänger-Themen 9
A Counter für die anzahl von regulären ausdrücken Java Basics - Anfänger-Themen 4
H Java - Counter Java Basics - Anfänger-Themen 2
M Counter erstellen - Was mache ich falsch? Java Basics - Anfänger-Themen 17
O Counter im JWindow mit Thread und dispose Java Basics - Anfänger-Themen 3
B Array via Schleife mit ungeraden bzw geraden Zahlen füllen Java Basics - Anfänger-Themen 7
A Summe aller ungeraden Zahlen Java Basics - Anfänger-Themen 5
B Wieso gibt er hier nur die ungeraden Zahlen aus? Java Basics - Anfänger-Themen 5
L Array: Summe aller geraden und ungeraden Zahlen ermitteln Java Basics - Anfänger-Themen 9
K Potenz mit Summer der ungeraden Zahlen Java Basics - Anfänger-Themen 14
K Problem mit ungeraden Zahlen Java Basics - Anfänger-Themen 5
onlyxlia Anzahl Random Zahlen mit Scanner abfragen und in Array speichern Java Basics - Anfänger-Themen 10
Ü Java Array - Buchstaben als Zahlen ausgeben Java Basics - Anfänger-Themen 22
P Aus Text Datei nur Zahlen übernehmen Java Basics - Anfänger-Themen 13
K Warum werden immer noch doppelte Zahlen ausgegeben ? Java Basics - Anfänger-Themen 13
M negative Zahlen bei Intervallen Java Basics - Anfänger-Themen 10
XWing Doppelte Zahlen im Array Java Basics - Anfänger-Themen 8
M 3 Zahlen miteinander vergleichen Java Basics - Anfänger-Themen 18
J Taschenrechner mit mehr als 2 Zahlen. Java Basics - Anfänger-Themen 18
O Zahlen aus einem char-array per char + Zeichen addieren Java Basics - Anfänger-Themen 2
B Alle Zahlen finden, die 3 bestimmte Ziffern enthalten? Java Basics - Anfänger-Themen 9
K Java gleicher Wert von Zahlen? Java Basics - Anfänger-Themen 5
I aus 2 random zahlen soll nur die ungerade summe der beiden genommen werden. Java Basics - Anfänger-Themen 13
J Operatoren Zahlen addieren Java Basics - Anfänger-Themen 13
JavaBeginner22 Java 2 Zufalls zahlen generieren. Java Basics - Anfänger-Themen 11
X Wie kann man ein Regex erstellen, die 8-Bit-Binär-Zahlen darstellen. Java Basics - Anfänger-Themen 1
M Stream mit den ersten n natürlichen Zahlen Java Basics - Anfänger-Themen 4
D Größtes Palindrom Produkt aus zwei dreistelligen Zahlen Java Basics - Anfänger-Themen 60
T Methode, die prüft ob in einem Int-Array maximal 2 Zahlen enthalten sind, die größer als ihr Vorgänger sind Java Basics - Anfänger-Themen 5
sserio Befreundete Zahlen Java Basics - Anfänger-Themen 7
AhmadSlack Verzweigungen zahlen multiplizieren Java Basics - Anfänger-Themen 4
padde479 Array Multiplikation der ersten n Zahlen Java Basics - Anfänger-Themen 7
U Lotto-Zahlen App Java Basics - Anfänger-Themen 34
berserkerdq2 Wie würde man einen regulären Ausdruck in Java schreiben, der prüft, dass zwei bestimtme Zahlen nicht nebeneinadner sind? Java Basics - Anfänger-Themen 3
H Arrays: Größten Zahlen Unterschied herausfinden Java Basics - Anfänger-Themen 20
bluetrix Programmieren eines Bots für Zahlen-Brettspiel Java Basics - Anfänger-Themen 9
J Zahlen bis zu einem bestimmten Grenzwert ausgeben Java Basics - Anfänger-Themen 11
00111010101 Objektorientiertes Programmieren mit Vererbung (Zahlen in Array verschwinden) Java Basics - Anfänger-Themen 3
P Zweidimensionales Array als Tabelle mit befüllten Zahlen Java Basics - Anfänger-Themen 10
W Wie ziehe ich von einer bestimmten Zahl, Zahlen ab, bis mein Ergebnis null beträgt? Java Basics - Anfänger-Themen 10
emx-zee Erste Schritte NullPointerException, Array mit zufälligen Zahlen füllen Java Basics - Anfänger-Themen 2
W Bestimmte Zahlen bei Math.random ausschließen? Java Basics - Anfänger-Themen 31
K Erste Schritte "Taschenrechner" zeigt keine Komma Zahlen an. Java Basics - Anfänger-Themen 8
P Drei Zahlen eines Würfelspiels auswerten Java Basics - Anfänger-Themen 7
H Häufigkeit von Zahlen ermitteln Java Basics - Anfänger-Themen 23
sashady Zahlen rekursiv zerlegen und Ziffern addieren Java Basics - Anfänger-Themen 38
H Zahlen kürzen Java Basics - Anfänger-Themen 2
ansystin Teilerfremde Zahlen ausgeben + Zahlenausgabe speichern Java Basics - Anfänger-Themen 3
B Häufigkeit einzelner Zahlen in einem Array Java Basics - Anfänger-Themen 6
nevel Programm für die Summer der Zahlen 1- 1ß Java Basics - Anfänger-Themen 12
jhCDtGVjcZGcfzug Fibonacci Zahlen rekursiv und iterativ Java Basics - Anfänger-Themen 21
H Eingegebene Zahlen mit Array ausgeben Java Basics - Anfänger-Themen 18
I 12 Spalten von jeweils 30 Zahlen in Konsole ausgeben Java Basics - Anfänger-Themen 6
R Array mit Unter- und Obergrenze ganze Zahlen dazwischen erscheinen nicht Java Basics - Anfänger-Themen 1
OZAN86 For Schleife von 1-50 die Zahlen werden durch ein Komma getrennt Java Basics - Anfänger-Themen 10
Bademeister007 Operatoren Alle Zahlen einer ArrayList die durch 5 teilbar ist Java Basics - Anfänger-Themen 2
mhmt_03 dafür sorgen, dass im JTextfield nur zahlen eingebbar sind Java Basics - Anfänger-Themen 9
Ianatrix Zahlen von a bis b berechnen Java Basics - Anfänger-Themen 7
P Wie kann ich die Zahlen dieses Arrays dividieren? Java Basics - Anfänger-Themen 2
P Nutzer entscheiden lassen, wie viele Zahlen dieser in ein Array eingeben möchte. Java Basics - Anfänger-Themen 6
T Bestimmte Zahlen ausgeben mit einer whilfe Schleife Java Basics - Anfänger-Themen 21
H Alle Geraden zahlen bis 10 ausgeben Java Basics - Anfänger-Themen 11
java3690 Liste mit zufälligen zahlen füllen Java Basics - Anfänger-Themen 27
macle Rekursive String Methode, Gerade Zahlen rausfiltern Java Basics - Anfänger-Themen 10
M Regex nur Zahlen und Punkt zulassen, Keine Eingabe(Leeres TextFeld) nicht zulassen Java Basics - Anfänger-Themen 6
L Mit Zahlen im String rechnen Java Basics - Anfänger-Themen 19
G Java eingelesene Zahlen Java Basics - Anfänger-Themen 2
D Zahlen werden falsch gekürzt :? Java Basics - Anfänger-Themen 27
H Ungerade Zahlen ausgeben von 1 bis 1000 Java Basics - Anfänger-Themen 8
C Positive und negative Zahlen mit Regex extrahieren Java Basics - Anfänger-Themen 8
N Wörter und Zahlen nach speziellen Wörtern ausgeben Java Basics - Anfänger-Themen 11
F Komplexe Zahlen auf verschiedene Weise addieren Java Basics - Anfänger-Themen 18
L Java Int-Array, Zahlen sortieren Java Basics - Anfänger-Themen 8
B Fibonacci Zahlen dynamische Programmierung Java Basics - Anfänger-Themen 7
V Erste Schritte Taschenrechner mit beliebig vielen Zahlen Java Basics - Anfänger-Themen 5
X Wie kann ich Zahlen in einzelne Zifferne zerlegen? Java Basics - Anfänger-Themen 3
J 10 positive Zahlen eingeben Java Basics - Anfänger-Themen 10
K Rechtsbündige Ausgabe von Zahlen Java Basics - Anfänger-Themen 6
A Wie zwei zahlen in einer Variable speichern? Java Basics - Anfänger-Themen 7
M Zahlen erraten Java Basics - Anfänger-Themen 7
E Zahlen von einem Array mit zahlen von zweitem Array vergleichen Java Basics - Anfänger-Themen 27
S Mit nextGaussian() positive Zahlen erzeugen? Java Basics - Anfänger-Themen 39
D auch negative Zahlen sotieren Java Basics - Anfänger-Themen 18
M Warum berechnet mein Primzahlenprog zu hohe Zahlen nicht? Java Basics - Anfänger-Themen 20
W Bell Zahlen Java Basics - Anfänger-Themen 2
H Min und Max von Zahlen Java Basics - Anfänger-Themen 10
der_Schokomuffin Fehler bei Zufallsgeneration von Zahlen Java Basics - Anfänger-Themen 7
J Erste Schritte Alle möglichen ausgaben von 5 Zahlen als Vector Java Basics - Anfänger-Themen 7
F Abstand zum Durchschnitt von 5 Zahlen berechnen... Java Basics - Anfänger-Themen 16
Moji Klassen Array Zahlen zu Sternchen (U-Helmich 7.1-4) Java Basics - Anfänger-Themen 5
F Summe aller echten Teiler und Zahlen zurückgeben Java Basics - Anfänger-Themen 1
T Perfekte Zahlen ausgeben Java Basics - Anfänger-Themen 12

Ähnliche Java Themen

Neue Themen


Oben