Java Gurus,
Derzeit haben wir eine HashMap<String,SomeApplicationObject>
, die häufig gelesen und gelegentlich geändert wird und wir haben Probleme, dass Lesen bei der Änderung / beim erneuten Laden null
zurückgibt. was nicht akzeptabel ist.
Um das zu beheben, habe ich folgende Optionen:
A. Verwenden Sie ConcurrentHashMap
Was wie die erste Wahl aussieht, aber die Operation, von der wir sprechen, ist reload()
- bedeutet clear()
gefolgt von replaceAll()
. Wenn also Map
nach clear()
und pre replaceAll()
gelesen wird, gibt es null zurück, was nicht wünschenswert ist. Selbst wenn ich synchronize
behebe, behebt dies das Problem nicht.
B. Erstellen Sie eine andere Implementierung basierend auf ReentrantReadWriteLock
Wo ich create Write Lock
vor reload()
operation erstellen würde. Dies scheint passender zu sein, aber ich denke, dass es dafür schon etwas geben muss und ich das Rad nicht neu erfinden muss.
Was ist der beste Ausweg?
BEARBEITEN Ist eine Sammlung bereits mit einer solchen Funktion verfügbar?
Es scheint, dass Sie nicht sicher sind, wie das, was Peter Lawrey vorschlägt, umgesetzt werden kann. Es könnte so aussehen:
%Vor%Es gibt keine Nebenläufigkeitsprobleme, weil:
getNewValues
muss nicht synchronisiert oder atomar sein map
ist atomar map
ist flüchtig, was garantiert, dass andere Threads die Änderung sehen Da Sie die Map neu laden, würde ich sie bei einem Reload ersetzen.
Sie können dies tun, indem Sie eine flüchtige Map verwenden, die Sie bei der Aktualisierung vollständig ersetzen.
Dies klingt ein Los wie Guavas Cache
, obwohl es wirklich darauf ankommt, wie Sie die Karte auffüllen und wie Sie die Werte berechnen. (Offenlegung: Ich trage zu Guava bei.)
Die eigentliche Frage ist, ob Sie angeben können, wie Sie Ihre SomeApplicationObject
mit der Eingabe String
berechnen. Nur basierend auf dem, was Sie uns bisher gesagt haben, könnte es in etwa so aussehen ...
Wenn Sie den Cache neu aufbauen möchten, rufen Sie einfach cache.invalidateAll()
auf. Mit LoadingCache
können Sie cache.get(key)
aufrufen und wenn der Wert noch nicht berechnet wurde, wird er neu berechnet. Oder vielleicht nach dem Aufruf von cache.invalidateAll()
, können Sie cache.loadAll(allKeys)
aufrufen, obwohl Sie immer noch einzelne Elemente laden können, falls zwischen den invalidateAll
und loadAll
eine Anfrage eingeht.
Wenn das nicht akzeptabel ist - wenn Sie nicht einen Wert einzeln laden können, müssen Sie alle auf einmal laden - dann würde ich mit Peter Lawreys Ansatz fortfahren - behalten Sie eine volatile
-Referenz bei eine Karte (im Idealfall ImmutableMap
), berechnen Sie die gesamte Karte neu und weisen Sie die neue Karte der Referenz zu, wenn Sie fertig sind.
Tags und Links java design locking reentrantreadwritelock concurrenthashmap