Der beste Weg, um eine ConcurrentHashMap an eine andere Klasse zu übergeben? - Java, Thread-Sicherheit, Singleton, Concurrenthashmap

Ich habe eine Handler-Klasse, die eine private ConcurrentHashMap enthält, die andere Klassen wollen, aber ich bin mir nicht sicher, der beste Weg, es ihnen zu geben.

Meine offensichtlichen Optionen sind ..

  1. Geben Sie die gesamte ConcurrentHashMap zurück (Beispielcode unten - das klingt gefährlich für mich, da CHMs nur von jeweils einem Thread verwendet werden sollen)
  2. Erstellen Sie jedes Mal eine neue HashMap, wenn Sie das Ganze zurückgeben möchten.
  3. Gib einen Iterator zurück ... aber ich hasse Iteratoren! Und es wären nur die Schlüssel oder die Werte.
public class StuffHandler {
private StuffHandler(){}
public static synchronized StuffHandler getInstance() {
return INSTANCE;
}
private final static ConcurrentHashMap<String, Stuff> myStuff = new ConcurrentHashMap<>();
public static ConcurrentHashMap<String, Stuff> getStuff() {
return myStuff;
}
}

Antworten:

1 für die Antwort № 1

So etwas gibt es nicht der beste Weg, um ein ConcurrentHashMap zu einer anderen Klasse. Alles hängt von Ihrem Anwendungsfall ab, d. H. Von dem, was Ihre Klassen tun sollen.

Sie haben drei Möglichkeiten:

  1. Gib die Karte wie folgt zurück:

    return myStuff;
    

    Dadurch können Ihre anderen Klassen das tatsächliche ändern myStuff Karte und jeder wird die Änderungen sehen. Jedoch, es wird kein Nebenläufigkeitsproblem geben, schon seit ConcurrentHashMap tatsächlich unterstützt den gleichzeitigen Zugriff (daher der Name), und es geschieht auf sehr effiziente Weise.

  2. Eine Kopie der Karte zurückgeben:

    return new HashMap(myStuff);
    

    Dadurch wird jeder Klasse, die Ihren Aufruf aufruft, eine neue Karte zurückgegeben getStuff() Methode. So kann jeder Anrufer mit dieser Karte herumspielen, da niemand sonst Änderungen sieht, weder andere Anruferklassen noch Ihre StuffHandler Klasse. Denken Sie daran, dass wenn die Karte groß ist, es könnte teuer werden um jedes Mal, wenn der Getter aufgerufen wird, eine Kopie zurückzugeben.

  3. Gebe ein unmodifizierbares zurück Aussicht der Karte:

    return Collections.unmodifiableMap(myStuff);
    

    Dies gibt keine Kopie der Karte zurück. Tatsächlich kopiert es nichts, sondern gibt stattdessen einen Wrapper Ihrer Map zurück, der keine Änderungen zulässt. Dies ist für die aufrufenden Klassen transparent getStuff(). Diese Option gibt eine Liveansicht der Karte zurück, also die aktuelle myStuff Karte wird nicht geändert (wenn eine Änderung über die zurückgegebene Karte versucht wird, ein UnsupportedOperationException wird geworfen). Dennoch, wenn die tatsächliche myStuff Karte wird geändert (durch eine Methode Ihrer StuffHandler Klasse), jede andere Klasse, die angerufen hat getStuff() werde diese Änderung sehen.


2 für die Antwort № 2

vorausgesetzt, dass CHMs nur von jeweils einem Thread verwendet werden sollen

Das ist einfach nicht korrekt. Der "gleichzeitige" Teil von ConcurrentHashMap bedeutet "sicher für die gleichzeitige Verwendung von mehreren Threads." Als die Javadoc Anmerkungen:

Eine Hash-Tabelle, die vollständige Parallelität von Abfragen und Hoch unterstützt erwarteter Nebenläufigkeit für Updates.

Wenn Sie nicht möchten, dass Ihr Konsument mutieren kann Map Sie können entweder eine Kopie erstellen (dann können Sie nicht einmal Updates sehen) oder mit ihr umbrechen unmodifyableMap (Kann Updates sehen).


1 für die Antwort № 3

Wenn Sie möchten, dass jedes Objekt, das die Map erhält, die gleichen Daten erhält und die von einer Klasse vorgenommenen Änderungen für die anderen Klassen sichtbar sind, möchten Sie "myStuff" direkt zurückgeben.

Wenn Sie möchten, dass jedes Objekt, das die Karte erhält, eine eigene Kopie hat und wenn Sie nicht möchten, dass von einem Objekt vorgenommene Änderungen vom anderen Objekt erkannt werden, geben Sie eine Kopie von "myStuff" zurück.


Speisekarte