24.6 Einkaufen - ein Beispiel |
|
Die Modellierung des schon in 24.5 beschriebene Szenarios lässt sich am einfachsten in einem Diagramm darstellen. Wir benutzen dazu die sog. UML-Notation, auf die wir später noch ausführlicher eingehen werden. | |
UML = Unified Modeling Language |
|
Diagramm lesen | Die
blauen Kästen symbolisieren Klassen, die wir selber schreiben, ihre Namen
stehen in der ersten Ableitungen. Die unteren Abteilungen werden wir später
benutzen. Die Klasse Thread ist rötlich gefärbt, um anzudeuten, dass
wir sie nicht implementieren. Die Klasse Kunde soll von der Klasse
Thread
erben. Dies wird in der UML-Notation durch einen Pfeil dargestellt, der an
seinem einen Ende ein ungefülltes Dreieck hat. Der Pfeil zeigt zu der
Klasse, von der geerbt
![]() |
Download: Einkaufswagen. java |
|
Bemerkungen |
Die Klasse Einkaufswagen besitzt nur
eine Methode: istInGebrauch().
In ihr wird der Gebrauch des Einkaufswagens mit Hilfe der
sleep()-Methode
simuliert. In unserem Fall bestimmt eine Zufallszahl zwischen
0
und 5000
die Dauer des Einkaufs. Beim Ein- in bzw. Ausstieg aus der Methode wird
der Name des Threads, der auf die Methode zugreift ermittelt und
ausgegeben. |
Download: Kunde.java |
|
Bemerkungen |
Die Klasse
Kunde
aggregiert einen Einkaufswagen, genauer: das
Einkaufswagen-Objekt
wagen wird einem Kunden-Objekt
bei seiner Erzeugen zugewiesen wird. Die von
Thread
geerbte
run()-Methode
wird überschrieben und ruft für den aggregierten
wagen
die Methode istInGebrauch()
auf. |
Schließlich benötigen wir noch eine
Klasse, die das ganze Szenario, das heißt Kunden und Einkaufswagen
verwaltet: Es ist dies die Klasse
Einkaufen.
Sie enthält die main()-Methode.
Ihre Rolle wird im UML-Klassendiagramm deutlich. Sie aggregiert die Klasse
Kunde
und Einkaufswagen.
Die beiden 1-en bei der Klasse Einkaufen sagen, dass ein
Einkaufswagen-
und ein Kunden-Objekt
nur zu einer Instanz von
Einkaufen gehören. Umgekehrt
kann Einkaufen
im Prinzip beliebig - genauer: zwischen null und unendlich viele -
Kunden-
und Einkaufswagen-Objekte
verwalten. Die wird durch 0..*
ausgedrückt. |
|
Download: Einkaufen.java |
|
Bemerkungen |
Um unser eigentliche Problem, die
Vermeidung von Konflikten bei parallelen Prozessen zu verdeutlichen
erzeugen wir nur einen wagen,
den wir den beiden Kunden fritz
und annerose
übergeben und damit Einkaufen schicken. |
Ausgabe |
Fritz geht Einkaufen! Annerose geht Einkaufen! Dauer des Einkaufs von Annerose: 2946 Annerose ist fertig Dauer des Einkaufs von Fritz: 3188 Fritz ist fertig |
Der Konflikt wird deutlich. Annerose geht schon Einkaufen, bevor Fritz mit dem Wagen zurück ist. Ja sie ist schon vor Fritz mit ihrem Einkauf fertig. Dass Annerose schon vor Fritz zurückkehrt ist nicht immer der Fall, da die Einkaufsdauer über einen Zufallsgenerator gesteuert wird. | |
Lösungs-variante 1 Download: |
Wir verändern Kunde (die beiden
anderen Klassen bleiben unverändert):
|
Der erste Thread holt sich für das
Objekt wagen
eine Sperre. Das bedeutet, dass solang dieser Thread die Sperre besitzt
kein weiterer Thread auf das Objekt
wagen
zugreifen kann. |
|
Ausgabe |
Fritz geht Einkaufen! Dauer des Einkaufs von Fritz: 4239 Fritz ist fertig Annerose geht Einkaufen! Dauer des Einkaufs von Annerose: 914 Annerose ist fertig |
Lösungs-variante 2
Download: |
Wir synchrionisieren die Methode
istInGebrauch(),
d.h. ein Objekte das über einen Thread auf diese Methode zugreifen,
besitzen eine Sperre, weitere Threads werden am Zugriff gehindert.
Die Klasse Kunde bekommt wieder ihre alte Gestalt.
|
Ausgabe |
Der Effekt ist derselbe. Die Ausgabe
unterscheidet sioch zur ersten Variante nur in den Einkaufszeiten. |
Fritz geht Einkaufen! Dauer des Einkaufs von Fritz: 3609 Fritz ist fertig Annerose geht Einkaufen! Dauer des Einkaufs von Annerose: 3962 Annerose ist fertig |
|
Probleme beim Locking (Sperren) |
![]() |
![]() Java ist auch eine Insel
Chrsitian Ullenboom: |
|
zu | 24.7 Threading mit Swing |
zur Startseite | www.pohlig.de (C) MPohlig 2004 |