Threads Abarbeiten

Miaming

Mitglied
Hallo zusammen, mal wieder eine Frage diesmal bezogen auf das Thema Threads - Die Aufgabe:

class Lager {
private int bestand;
private static final int kapazität = 20;

public void einlagern() {
if (bestand+5 <= kapazität) {
bestand+=5;
System.out.println("nach einlagern :" + bestand);
}
}

public void entnehmen() {
if (bestand-3 >= 0) {
bestand-=3;
System.out.println("nach entnehmen :" + bestand);
}
}
}

Ein Produzenten-Thread-Objekt versucht in einer Endlosschleife jeweils Waren einzulagern,
wie der folgende Java-Quelltext zeigt:

class ProduzentThread extends Thread {
private Lager lager;

ProduzentThread(Lager lager) {
this.lager = lager;
}

public void run() {
while(true){
lager.einlagern();
}
}
}

Analog dazu versucht ein Konsumenten-Thread-Objekt in einer Endlosschleife jeweils Waren
aus dem Lagerbestand zu entnehmen. Der Quelltext ist analog zum Produzenten gestaltet. In
der while-Schleife wird hier die Methode lager.entnehmen() aufgerufen.

In ihrer Main-Methode wird jeweils ein Objekt der Klasse Lager, ProduzentThread und
KonsumentThread angelegt (vgl. Skizze). Anschließend wird erst pt.start() und
dann kt.start() aufgerufen.


Die Ausgabe:

Java:
Eine Ausführung der Anwendung führt zu folgender Ausgabe:      
         ........... 
nach entnehmen :  1 
nach einlagern :   6    
nach einlagern :  8         
nach einlagern :    13           
nach einlagern :  18 
nach entnehmen :  3 
nach entnehmen : 15 
nach entnehmen : 12

Das allgemeine Grundproblem welches ich habe, ist die Tatsache dass ich schon nicht weiß, wie die erste Ausgabe überhaupt zu Stande kommt.

Könnte mir jemand irgendwie nen bisschen erklären, wie das Programm arbeitet? Nach welchen Schritten? Also es scheint so als würde ich den Zusammenhang zwischen Threads und dem Programm nicht im Ansatz verstehen, deshalb hoffe ich darauf dass mir es jemand anfängerfreundlich erklären könnte

Ich bedanke mich voraus!
 
danke für den tipp!

setzte ich den haltepunkt dort, wo ich den wert wissen möchte? also bei "int bestand" ? in meiner lager klasse?
 
Hi,
die Ausgabe die du bei diesem Programm erhälst wird zu 99,99% in aller Fälle immer unterschiedlich sein. Das liegt daran, dass die 2 Threads (ProduzentThread und KonsumentThread) unterschiedlich vom Betriebssystem-Scheduler bearbeitet werden.
Da in der Aufgabenstellung steht, dass der ProduzentThread vor dem KonsumentThread gestartet wird, wird der Scheduler zu erst diesen Thread arbeiten lassen. Je nach Hardwarevoraussetzungen und Scheduler läuft dieser Thread dann eine bestimmte Zeit, bevor der KonsumentThread bearbeitet wird.

Desweitern musst du beachten, dass die Methoden einlagern() und entnehmen() bzw die Variable bestand nicht syncronized ist, was bedeutet, dass auf diese Variable von mehreren Threads "gleichzeitig" zugegriffen werden kann und dadurch eine inkonsistenz im Programmablauf entstehen kann.
Genau aus diesem Grund vermute ich mal, dass bei deiner Ausgabe als erstes eine 1 steht. Ich würde mir das folgendermaßen erklären:
ProduzentThread ruft die Methode einlagern auf, wobei auf die Variable bestand in byte-Ebene die 5 Einheiten dazugerechnet werden. Während der ProduzentThread eben diese 5 Einheiten draufrechnet, fragt der KonsumentThread mit der Methode entehmen die Variable bestand ab und rechnet -3 wieder auf byte-Ebene, obwohl der andere Thread noch am summieren ist.

Um das ganze mal ein wenig zu veranschaulichen:
Scheduler bearbeitet 1 Thread...
ProduzentThread: einlagern()
bestand = 1
bestand = 2
bestand = 3
bestand = 4
// Hier unterbricht der Scheduler den Thread
Scheduler bearbeitet 2 Thread...
KonsumentThread: entehmen()
bestand = 3
bestand = 2
bestand = 1
System.out.println(bestand) // = 1
Scheduler bearbeitet 1 Thread...
ProduzentThread: einlagern()
... und so weiter....


Oder deine Variable bestand startet nicht bei dem Wert 0 sondern bei -1, wobei mich das doch sehr täuschen würde.

Ich würde dir mal empfehlen vor die If-Bedingung von beiden Methoden eine Ausgabe einzubinden, damit du vor der Berechnung siehst, welcher Thread gerade arbeitet.

Gruß

Fabio
 
zum debugger: mit rechte Maustaste | toggle Breakpoint setzt du einen Haltepunkt nach der Ausführung von dem Inhalt der aktuellen Zeile.
 
Hallo Fabio, deine Erklärung scheint mir als sehr einleuchtend und verständlich! Vielen für die Antwort! Ich glaube ich habe den Vorgang / die Abarbeitung der Threads anhand des Beispiels besser verstanden!

@genodeftest: Das mit dem Debugger hat nur bedingt funktioniert :S Ich hab die jeweiligen Klassen und Methoden erstellt.

Habe dann nach der Zeile private int bestand den breakpoints gesetzt und den Debugger ausgeführt (von der klasse test - da wo die main steht) allerdings beginnt dann schon die endlosschleife zu laufen - benötige ich einen weiteren Breakpoint? (sorry is vielleicht doof de frage allerdings bin ich mit dem ganzen nicht so vertraut )
 
sorry für den doppelpost aber ich habe doch noch eine frage dazu an dich fabio:

und zwar hast du geschrieben, dasss der produzententhread zuerst gestartet wird, was ja auch der aufgabenstellung entspricht! erst wird der produzententhread gestartet

Java:
pt.start();
im Anschluß erfolgt die Ausführung des Konsumententhreads! (nach entnehmen: 20, nach entnehmen 17... ) Allerdings frage ich mich dann, warum als erstes die Ausgabe des Konsumententhreads erfolgt?

Du hast recht, die Ausgaben erscheinen randommäßig gestern erhielt ich andere Ausgaben als heute allerdings bekomme ich immer zuerst die Ausgabe die Ausgabe "nach entnehmen" obwohl diese Methode im Konsumententhread bearbeitet wird - allerdings wird der Thread ja später gestartet wieso kommt es dann zu dieser Ausgabe? also warum erfolgt ich als erstes die Ausgabe des Produzententhreads, wenn dieser ja als erstes gestartet wird?
 
Wenn man mit Threads arbeitet kann man sich nie zu 100% auf die Konsole verlassen, da die Ausgabe immer Zeitversetzt zur eigentlich Ausführung kommt.

Allerdings kann ich mir nicht vorstellen, dass die Variable bereits auf 20 gesetzt wurde, ohne eine Ausgabe vorher gemacht zu haben. Kann es evtl. sein, dass die Konsole nach unten gescrollt hat und du nur den unteren Teil gelesen hast?
 
Danke der Beitrag wurde von einem Admin wohl gelöscht, weil ich eine zulange Ausgabe gepostet habe: Ich poste nun hier mal eine kürzere Ausgabe die ich erhalte wenn ich das Programm ausführe:

Java:
nach einlagern :20
nach entnehmen :20
nach entnehmen :17
nach entnehmen :19
nach entnehmen :16
nach entnehmen :13
nach entnehmen :10
nach entnehmen :7
nach entnehmen :4
nach entnehmen :1
nach einlagern :19
nach einlagern :6
nach einlagern :8
nach einlagern :13
nach einlagern :18
nach entnehmen :3
nach einlagern :20
nach entnehmen :20

gestern erhielt ich widerum ne komplett andere ausgabe.... und es wurde auch nicht mit der methode "nach einlagern" aus dem Produzententhread gestartet, sondern mit der Methode "nach entnehmen" aus dem Konsumententhread ... issn bisschen mysteriös das ganze... auf wunsch poste ich gerne dazu den vollständigen quelltext den ich aus der vorgegeben aufgabenstellung gebastelt habe

frohes neues an alle btw ;)
 
Hi und auch dir ein frohes Neues,
vielleicht könntest du uns mal genau sagen, was du bei dieser Aufgabe nicht verstehst. Bzw. was du in dieser Aufgabe machen musst, wo du nicht weiter kommst.
 

Neue Beiträge

Zurück