Was ist der beste Weg, um diesen Code threadsicher zu machen?
%Vor%Hier sind die paar Lösungen, an die ich denken könnte:
ConcurrentHashMap
verwenden, aber wenn ich es gut verstanden habe, macht es nur die atomaren put
und get
Operationen threadsicher, dh es stellt nicht sicher, dass buildB()
Methode, die nur einmal für einen bestimmten Wert aufgerufen wird. Collections.synchronizedMap(new HashMap<A, B>())
verwenden, aber ich hätte das gleiche Problem wie der erste Punkt. putIfNeededAndGet()
Methode synchronized
setzen, aber ich kann wirklich viele Threads haben, die auf diese Methode zugreifen, also könnte es ziemlich teuer sein. Welche anderen Lösungen könnte ich haben?
Ich weiß, dass dies ein ziemlich häufiges Thema im Web ist, aber ich habe noch kein klares, vollständiges und funktionierendes Beispiel gefunden.
Dies ist möglicherweise nicht die Antwort, die Sie suchen, aber verwenden Sie die Guava CacheBuilder
, das macht schon alles und noch mehr:
Sie können auch einfach das zeitgesteuerte Ablaufdatum und andere Funktionen hinzufügen.
Dieser Cache stellt sicher, dass load()
(oder in Ihrem Fall buildB
) nicht gleichzeitig mit demselben key
aufgerufen wird. Wenn ein Thread bereits ein B
erstellt, wartet jeder andere Aufrufer nur auf diesen Thread.
Verwenden Sie ConcurrentHashMap und das Lazy-Init-Muster, das Sie verwendet haben
%Vor% In der obigen Lösung ist es möglich, dass viele Threads die Klasse processB(...)
gleichzeitig haben und alle berechnen. Aber in meinem Fall benutze ich Future
und einen einzelnen Thread bekomme nur den alten Wert als null
daher wird nur der processB
Rest berechnet wird auf f.get()
warten.
Dachte vielleicht, dass dies auch für jemand anderen nützlich sein wird. Mit Java 8 lambdas habe ich diese Funktion erstellt, die für mich großartig funktioniert hat:
%Vor%Dann kannst du es so benutzen:
%Vor%Ich habe dies für etwas Bestimmtes erstellt, aber den Kontext und den Code zu einem allgemeineren Aussehen geändert, deshalb hat meine creationFunction einen Parameter, er kann auch keine Parameter haben ...
auch Sie können es mehr generieren, indem Sie Object in einen generischen Typ ändern, wenn es nicht klar ist, lassen Sie es mich wissen und ich werde ein weiteres Beispiel hinzufügen.
UPDATE:
Ich habe gerade von Map.computeIfAbsent erfahren, was im Grunde dasselbe ist, ich liebe java 8 :)
Tags und Links java multithreading map