Einmalige Rückgabe eines Wertes?

muckelzwerg

Bekanntes Mitglied
Da ich sowas gerade zurechtgefummelt habe, stell ich das mal zur Diskussion.
Ihr habt ein Objekt, mit einem Attribut, das ihr an ein anderes Objekt übergeben wollt.
Allerdings könnt ihr die Referenz nicht verwenden, wegen unterschiedlichen Threads, oder weil ihr das Attribut übers Netzwerk verschiebt, etc.
Das Attribut wird also beim Aufruf von "get..." kopiert.

Jetzt wollt ihr das Kopieren des Attributs möglichst reduzieren, weil es "teuer" ist. (egal welche Kosten)
Von einem get()-Aufruf zum anderen, muss sich das Attribut nicht zwangsläufig verändert haben. Ihr könnt also dem Aufrufer die Verantwortung zuschieben, die letzte Kopie aufzubewahren, bis er eine Neue bekommt.
Da entsteht dann sowas wie eine "OneTimeCopy", bei der entweder das Attribut kopiert oder null zurückgegeben, oder eine Exception ausgelöst, oder irgendein anderes Signal übetragen wird.
Aufrufen -> Kopie
nochmal Aufrufen -> keine Änderung -> "null"
nochmal Aufrufen -> neue Daten -> neue Kopie

Zusätzlich gilt, dass ihr kein aktives "Senden bei Änderung" nutzen könnt. Ist technisch nicht möglich, oder kostet noch mehr ...
Ihr müsst mit wiederkehrenden Abfragen umgehen, zwischen denen sich das Attribut gar nicht, oder sogar mehrfach geändert haben kann.

zurechtgefrickelt ist sowas schnell, aber wie würdet ihr das machen "dass es sich gut anfühlt"? ;)
 

Andi_CH

Top Contributor
Hm, warum soll das Attribut denn per get geholt werden? (Das aller erste mal ok, aber danach nicht mehr) Der Setter soll es schreiben wenn es sich verändert.
 

muckelzwerg

Bekanntes Mitglied
Ja, allerdings wird das Attribut in verschiedenen Threads genutzt. Derjenige, der es geholt hat, arbeitet vielleicht gerade damit, während der Setter es ändert.

Typische Reaktion -> Wechselseitiger Ausschluss
Den möchte man in diesem Fall wegen Leistungsverlust nicht haben.
Aufgrund der hohen Abfrageraten ist es aber akzeptabel, wenn der Verbraucher eine alte Kopie verwendet und erst beim nächsten Aufruf die Aktualisierte bekommt.

Zu den Raten:
Die Abfragerate ist relativ konstant und liegt irgendwo zwischen 10Hz und 100Hz.
Das Attribut muss sich über längere Zeit (Minuten) gar nicht unbedingt verändern, können sich aber auch innerhalb einer Sekunde 200mal ändern.

Zu den Kardinalitäten:
Abfrager gibt es nur wenige (<10). Objekte die abgefragt werden gibt es mehr (bspw ~50).
 

André Uhres

Top Contributor
Der Anrufer könnte die Referenz seiner Kopie als Parameter an die getter Methode übergeben. Ist die Kopie gleich dem Original, wird null zurückgegeben, sonst wird eine neue Kopie zurückgegeben.

Gruß,
André
 

muckelzwerg

Bekanntes Mitglied
Ja, das ist auch eine Möglichkeit.
Vielleicht sollte ich dazusagen, dass der Anbieter des Attributs weiß, wann es sich ändert (er schreibt die Änderungen ja). Er kann also auch ein "changed" Flag setzen und dem Verbraucher bei Anfrage den neuen Wert geben.
(Sorry, war für mich natürlich klar.)

Soweit ganz gut. Aber was passiert nun, wenn wir die Verbraucherzahl auf >1 erhöhen.
Entscheidet das Objekt selbst, wenn es eine neue Kopie rausgibt, dann müsste es sich die Verbraucher merken.
Sonst kommt C1 und holt eine Kopie, das Objekt geht auf "unchanged" und C2 bekommt "null", obwohl er noch keine Kopie hat.

Da ist Deine Variante mit dem Referenzvergleich wieder besser, weil C2 dann "null" übergibt und trotz unveränderter Werte eine Kopie bekommt.
Weniger schön ist, dass die Objekte dann verglichen werden müssen. Das macht auch wieder relativ viel Aufwand. (Sidequest: Wieviel Aufwand im Vergleich zum kopieren?)
Und wenn jeder Verbraucher jedes Objekt anfragt, haben wir #Verbraucher * #Objekte Kopien im Speicher rumliegen.
Bei 10 Verbrauchern und 100 Objekten, sind das schon 1000 kopierte Attribute.
Ist auch wieder nicht ganz so schön.
 

Andi_CH

Top Contributor
Ja, allerdings wird das Attribut in verschiedenen Threads genutzt. Derjenige, der es geholt hat, arbeitet vielleicht gerade damit, während der Setter es ändert.

Aehm - das Problem hast du aber auch in umgekehrter Richtung - Einer will es lesen während es ein Anderer gerade bearbeitet :) Um gegenseitigen Ausschluss wirst du nicht herumkommen.

IMO ist pollen über einen teuren Kanal schlechter als putten ... so rein per Definition - es gibt unnötigen traffic.

Ich habe eine sehr ähnliches Problem schon einmal gelöst:
Konkret behandelt habe ich das Problem in einem Kommunikations-Proxy. Da gab es zig setter (um zu senden) für alle möglichen Messagetypen und jede hat zuerst die Message geschrieben, dann unter Schutz ein Flag dass eine neue Meldung da ist.

Dieses Flag schützte auch vor überschreiben der Message, falls die noch nicht abgeholt wurde - es gab aber auch Messages die überschrieben werden durften - das wusste nur die Message selbst.

Um zu senden wurde die Meldung (natürlich wieder unter Schutz) kopiert.

(Empfangsseitig sah es ähnlich aus, einfach mit gettern)

Ziel war natürlich, dass der teure Kanal so optimal wie möglich ausgenutzt war.
 
Zuletzt bearbeitet:

muckelzwerg

Bekanntes Mitglied
Ich sag auch nicht, dass es eine universelle Lösung für jede denkbare Variante gibt.
Wenn ich einen oder mehrere Verbraucher habe, die alle eine eigene Kopie besitzen, dann können sie mit der Kopie arbeiten, wie sie wollen.
Wobei ich mit "arbeiten" in erster Linie lesen und nicht schreiben meine, da der Anbieter die Hoheit über die Werte hat. Es bringt dem Verbraucher ja nichts, die Werte seiner Kopie zu ändern, wenn sie niemals zurückgeschrieben werden.

Jetzt hör ich Dich gleich sagen "Wenn sie alle nur lesen, brauchst Du auch die Kopie nicht".
Leider ist das Attribut im Original nicht threadsafe. Wenn einer der Verbraucher bspw. eine Anzeige mit den Werten des Attributs füllen will und der Anbieter gerade die Werte ändert ... krachts.
Desweiteren sind veraltete Zustände in Ordnung, ein gemischter Zustand, der bei gleichzeitigem Zugriff auf Listen entstehen könnte, aber nicht.



Momentan bin ich bei folgender Variante.
Der Anbieter besitzt einmal das Originalattribut und eine "interne Kopie".
Wird das Attribut angefragt, dann überprüft er, ob die Kopie noch aktuell ist.
Ist sie das, gibt er die Referenz der Kopie heraus. Ist sie es nicht, erzeugt er eine funktionslokale neue Kopie und weist diese dann der internen Kopie zu. Anschließend gibt er wieder die Referenz heraus.
Das reduziert die Kopien auf die Anzahl der Objekte und erlaubt einen mehrfachen, gleichzeitigen Zugriff.


In meinem Fall ist das originalAttribut jedoch eine HashMap und die Kopie ein Vector.
Der Vector ist "threadsafe", aber das garantiert mir nur, dass es nicht raucht. Es garantiert nicht, dass ich immer einen konsistenten Zustand bekomme.
Deswegen die funktionslokale Kopie mit anschließender Zuweisung.
Bei mehreren Verbrauchern in unterschiedlichen Threads könnten dann gleichzeitig mehrere funktionslokale Kopien erzeugt und die interne Kopie mehrfach überschrieben werden. Das wäre soweit kein Problem, da bei jedem Überschreiben immer eine konsistente Kopie zugewiesen wird.

Leider verschiebe ich damit das Konsistenzproblem nur zur HashMap, die mir da keine Garantien machen kann.
Wenn der Verbraucher das Attribut anfragt, kann es sein, dass der Anbieter gerade neue Messdaten in die HashMap einträgt.
Gleichzeitig liest aber der Verbraucher ebenfalls die Hashmap aus einem anderen Thread heraus, indem er die Get-Methode ausführt.
Ist das changed-Flag gesetzt, dann wird aus der HashMap ein neuer Vektor kopiert. Der kann nun wieder inkonsistent sein.
Auch das sollte sich wieder mit einer funktionslokalen Kopie und Zuweisung beheben lassen, ohne Synchronization verwenden zu müssen.
(Der Anbieter ist IMMER singlethreaded)


So und jetzt noch zum "Put". ;) Das Problem ist, dass sich bei manchen Objekten das Attribut extrem schnell ändert. 200Hz und mehr.
Wenn ich da jedesmal eine Kopie mache, ist das eine ziemliche Verschwendung, da die Kopien noch mehrfach überschrieben werden, bevor ein Verbraucher sie wieder abfragt.
Die Verbraucher kommen zwar einigermaßen regelmäßig, aber die Anbieter wissen nicht genau wann. Sie können also nur über die Abfrage erfahren, ob das Attribut gewünscht wird und in dem Moment schauen, ob die Kopie aktualisiert werden muss.


Letztlich bliebe noch statt der HashMap (ist hier eh nur ein Beispiel) einen wirklich sicheren Container zu verwenden, so dass man die Referenz rausgibt und alle Verbraucher lesen, wie es ihnen passt.
Das ist aber auch wieder nicht gewünscht, weil damit die Kontrolle über das Originalattribut abgegeben wird und Veränderungen nicht mehr überprüft werden können. Der Anbieter kontrolliert intern und sorgt dafür, dass er nur legale Werte einträgt.
Gibt er die Referenz auf das Original heraus, kann da wieder viel anstrengendes Zeug passieren.


Na, spielt noch jemand mit? ;)
 
Zuletzt bearbeitet:

muckelzwerg

Bekanntes Mitglied
Damit caste ich die Referenz auf eine abgeleitete MapKlasse, die bei Schreiboperationen eine Exception wirft.
Hm ...
Die Verbraucher sind nicht in der Lage direkt mit der Map zu arbeiten. Unter anderem werden damit JTables gefüllt.
Wenn ich die Kopie komplett spare will, müsste ich noch ein TableModel für die HashMap bauen. (oder klauen ^^)

Was ich jetzt nicht sehe (vielleicht übersehen), wie das mein Konsistenzproblem löst. Wenn ich während des Füllens der Map zugreife, bekomme ich dennoch wieder einen unerlaubten Zustand. Und den bekomm ich dann wieder nur mit Synchronisation oder einer Kopie weg.

Nehmen wir an ich verwende die unmodifiable HashMap direkt, ohne Vektor oder Kopie.
Dann müsste ich ein Lock auf das Lesen setzen und das auch noch in einem TableModel verwenden ... riecht noch blöder.

Wie ist Folgendes:
Eine lokale Referenz auf die HashMap, gecastet als unmodifyable. Diese Referenz ruft der Verbraucher nun JEDESMAL ab, wenn er das Attribut verwenden will.
Der Anbieter schreibt neue Werte erst in eine funktionslokale Kopie. Das kostet dann einen zusätzlichen Konstruktor.
Nach dem Schreiben der Werte aktualisiert er die unmodifiable Referenz.
Wenn ein Verbraucher beim Lesen unterbrochen wird, dann schreibt der Anbieter in das zweite Objekt. Selbst wenn er durchläuft und die Referenz aktualisiert, bekommt der Verbraucher davon nichts mit, weil er seine Referenz auf das alte Objekt verweist. (Call by Value of Reference quasi) Damit liest er einen konsistenten Zustand, auch wenn er suspendiert wird und der Anbieter die Werte ändert.

Was mir daran noch nicht gefällt ist, dass der Verbraucher die alte Version am Leben erhält und erst an die GC übergibt, wenn er neu anfragt.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
A einmalige Ausführung eines Methodenabschnittes Allgemeine Java-Themen 3
S einmalige Initialisierung Allgemeine Java-Themen 7
D einmalige Zufallszahlen erstellen Allgemeine Java-Themen 10
M [SOLVED]MVC, einmalige aktionen Allgemeine Java-Themen 7
S Rückgabe einer HttpURLConnection für eine Seite einlesen bei der man eingeloggt ist..? Allgemeine Java-Themen 5
R Rückgabe eines Arrays durch Funktion Allgemeine Java-Themen 9
D Problem mit der Rückgabe von Raw-Types Allgemeine Java-Themen 2
S Java Problem bei der Rückgabe eines Arrays Allgemeine Java-Themen 19
S Polymorphie generischer Rückgabe-Typ Allgemeine Java-Themen 4
R Methoden Rückgabe Arrays aufangen Allgemeine Java-Themen 29
H SQL Update "Rückgabe der DB als String?" Allgemeine Java-Themen 7
Redfrettchen Rückgabe nicht sinnvoll: Exception oder null zurück? Allgemeine Java-Themen 9
S Rückgabe Allgemeine Java-Themen 6
R Rückgabe 2 Werte Allgemeine Java-Themen 5
I Rückgabe eines Arrays aus einer Methode, wie sicher? Allgemeine Java-Themen 3
O regulärer Ausdruck zum durchsuchen eines Strings verwenden Allgemeine Java-Themen 2
T Rotationswinkel eines Bildes bestimmen Allgemeine Java-Themen 4
C Probleme beim Erstellen eines runnable-jar files Allgemeine Java-Themen 1
J JavaScript innerhalb eines Java Projekts ausführen Allgemeine Java-Themen 2
Encera Größe eines Objektes in Byte berechnen Allgemeine Java-Themen 2
8u3631984 Prüfen ob min. ein Element eines Sets in einem anderen Set enh Allgemeine Java-Themen 4
M Array Rang eines Elements Allgemeine Java-Themen 4
OnDemand Teile eines Links entfernen Allgemeine Java-Themen 6
H Auslesen eines (LDAP-)Attributs in Active Directory Allgemeine Java-Themen 2
W JSON parsen eines ,mit JS.stringify erstellten Strings Allgemeine Java-Themen 27
H Textposition eines gedrehten Textes verschieben Allgemeine Java-Themen 8
berserkerdq2 run-methode eines Threads so programmieren, dass 30x die Sekunde etwas ausgeführt wird. Allgemeine Java-Themen 44
E Ersetzen eines Bildes in der Kopfzeile eines Word-Docx-Dokuments mit Apache POI XWPF Allgemeine Java-Themen 0
N Fahrtrichtung eines selbstfahrenden Auto ändern Allgemeine Java-Themen 3
T Letztes Zeichen eines Strings enfernen Allgemeine Java-Themen 14
S Übergabe eines Sortierkriteriums für ein Artikel Array mittels BiPredicate<Artikel, Artikel> Allgemeine Java-Themen 13
gotzi242 Schatzsuche mithilfe eines O(log n) Algorithmus Allgemeine Java-Themen 2
C Koordinaten LONG/LAT eines neuen Punktes in bestimmter Entfernen und Winkel berechnen Allgemeine Java-Themen 3
Tobero Meine Funktion für das beinhalten eines Punktes in einem Kreis funktioniert nicht Allgemeine Java-Themen 5
LimDul Direktes return eines Array geht nicht Allgemeine Java-Themen 20
S Mittelwert anhand eines Stream berechnen Allgemeine Java-Themen 5
kodela Breite eines erweiterten Monitors feststellen Allgemeine Java-Themen 5
R Zeilen eines 2d Arrays abwechselnd links und rechts mit Nullen auffüllen Allgemeine Java-Themen 14
Zrebna Alternative Darstellung eines Codesnippets Allgemeine Java-Themen 33
kodela Inhalt eines Arrays ändert sich mysteriös Allgemeine Java-Themen 2
bueseb84 Wget mit Wildcards - oder wie lädt man bei JFrog die letzte Version eines Artifacts herunter Allgemeine Java-Themen 3
N Erkennen eines Programs Allgemeine Java-Themen 2
N Pausieren eines Programmes Allgemeine Java-Themen 4
D Input/Output Implementierung eines CommandHandlers/Parsers für viele Eingaben Allgemeine Java-Themen 26
M Gibt es eine API die den aktuellen Wert eines Indikators beim Trading zurückgibt? Allgemeine Java-Themen 7
F Wie bekommt man alle Filenamen eines Webserver Verzeichnisses Allgemeine Java-Themen 6
A Fehler beim Öffnen eines Projekts Allgemeine Java-Themen 6
N Eigenschaften eines Buttons per Setter verändern Allgemeine Java-Themen 5
S Ausfuehrung eines Programms aufzeichnen..? Allgemeine Java-Themen 4
X Ermittlung eines doppelte Paars mit Streams Allgemeine Java-Themen 50
Stonie Prüfen von direkter Implementierung eines Interfaces Allgemeine Java-Themen 7
S Vorbereitung eines Praktikums Allgemeine Java-Themen 4
H Aufruf eines Web Service anhand übergebenen Parameter Allgemeine Java-Themen 2
M Weiterleiten von empfangenen Nachrichten eines StompSessionHandlers Allgemeine Java-Themen 1
J Programm zum Suchen eines Wortes im Dateisystem Allgemeine Java-Themen 4
H Rename eines Projekts Allgemeine Java-Themen 1
J Fenstergröße eines anderen Programmes auslesen Allgemeine Java-Themen 9
ReinerCoder auf Klassen innerhalb eines package zugreifen Allgemeine Java-Themen 22
Meeresgott Erste Schritte Sourcetree - Git | Suchen eines Commits Allgemeine Java-Themen 2
E Status eines USB Mikrofon abfragen Allgemeine Java-Themen 2
DaCrazyJavaExpert OOP Ansätze und Tipps zum Porgrammieren eines Taschenrechners Allgemeine Java-Themen 25
A OOP Problem beim Berechnen der größten Fläche eines Ringes Allgemeine Java-Themen 19
JavaNewbie2.0 Start eines Anderen Programm erkennen Allgemeine Java-Themen 6
I Verbindung eines Java-Plugins mit Webserver Allgemeine Java-Themen 3
L Auswertung eines Testes funktioniert nicht Allgemeine Java-Themen 37
G Iteratoren - Wie kann man mithilfe von Iteratoren nur jeden zweiten Wert eines TreeSets ausgeben? Allgemeine Java-Themen 4
GreenTeaYT Elemente eines 2Dim LinkedList von links nach rechts ausgeben? Allgemeine Java-Themen 0
B Spalten eines 2d-Arrays Allgemeine Java-Themen 2
M Rechenprogramm eines wissenschaftlichen Taschenrechners Allgemeine Java-Themen 4
S Eigenschaften (hier Verknüpfung) eines Files lesen Allgemeine Java-Themen 2
E Typüberprüfung eines chars Allgemeine Java-Themen 5
H Hilfe bei Erstellung eines Hilfe Fenster bei Tastendruck (F1 bei Win98) Allgemeine Java-Themen 5
T Teile eines Double-Wertes verändern Allgemeine Java-Themen 2
H Datentypen Typ eines Arrays überprüfen Allgemeine Java-Themen 9
RalleYTN DPI eines Bildes ändern Allgemeine Java-Themen 4
N Methoden Methoden einer Klasse auf Grundlage eines Strings aufrufen Allgemeine Java-Themen 6
K Bestimmten Bereich eines Strings lesen Allgemeine Java-Themen 6
C -Verschiedene Versionen eines Programms verwalten Allgemeine Java-Themen 7
O Datentypen Erstellung eines Containers, der verschachtelte Map-Strukturen beherbergen kann Allgemeine Java-Themen 0
F CPU Last eines Thread ausfindig machen Allgemeine Java-Themen 0
L Menge der Buchstaben eines Textes zählen Allgemeine Java-Themen 3
F Teil eines Bildes laden Allgemeine Java-Themen 1
Neumi5694 Operatoren regEx für das Erstellen eines Strings verwenden Allgemeine Java-Themen 3
P Löschen eines keys in einer SortedMap Allgemeine Java-Themen 5
RalleYTN Input/Output URL eines Zip Entry? Allgemeine Java-Themen 2
S Alle Methodenaufrufe eines Threads notieren..? Allgemeine Java-Themen 7
J NullPointerExeption bei Inizialisierung eines Arrays Allgemeine Java-Themen 3
I Setzen und Lesen eines Objektes (Enum?) Allgemeine Java-Themen 10
L Implementierung eines AVT-Baums Allgemeine Java-Themen 2
D Größe der Zahlenkombinationen eines Arrays begrenzen Allgemeine Java-Themen 3
D Objekt entlang eines Funktionsgraphens bewegen Allgemeine Java-Themen 6
B Existenz eines Files max 30 sec prüfen Allgemeine Java-Themen 5
U Koordinaten alle Pixel eines Dreiecks zeichnen ausgeben Allgemeine Java-Themen 5
P Wie funktioniert das Feedback eines Klicks auf eine Java GUI Allgemeine Java-Themen 10
thet1983 nach teilen eines Dateinamens suchen Allgemeine Java-Themen 6
T Bezeichnung eines Objektes mit String/int kombinieren Allgemeine Java-Themen 3
Z Auswerten eines eingegeben Termes Allgemeine Java-Themen 13
X Registrierung eines Ecore-Models außerhalb der Eclipse-Umgebung Allgemeine Java-Themen 0
R Instanzen eines Programms Allgemeine Java-Themen 8
I Arbeitsmaterialien eines Softwareentwicklers? Allgemeine Java-Themen 7

Ähnliche Java Themen

Neue Themen


Oben