Met behulp van Guava’s MapMaker

1. Inleiding

MapMaker is een bouwersklasse in Guava die het gemakkelijk maakt om threadveilige kaarten te maken.

Java ondersteunt al WeakHashMap om zwakke referenties voor de sleutels te gebruiken. Maar er is geen kant-en-klare oplossing om hetzelfde voor de waarden te gebruiken. Gelukkig, MapMaker biedt eenvoudige bouwer-methoden om te gebruiken Zwakke referentie voor zowel de sleutels als de waarden.

Laten we in deze tutorial kijken hoe MapMaker maakt het gemakkelijk om meerdere kaarten te maken en zwakke referenties te gebruiken.

2. Maven Afhankelijkheid

Laten we allereerst de Google Guava-afhankelijkheid toevoegen, die beschikbaar is op Maven Central:

 com.google.guava guave 29.0-jre 

3. Een voorbeeld van caching

Laten we eens kijken naar een eenvoudig scenario waarbij een server een aantal caches onderhoudt voor de gebruikers: een sessiecache en een profielcache.

De sessiecache is van korte duur en de vermeldingen worden ongeldig nadat de gebruiker niet langer actief is. De cache kan dus de invoer voor de gebruiker verwijderen nadat het gebruikersobject is verwijderd.

De profielcache kan echter een hogere time-to-live (TTL) hebben. De vermeldingen in de profielcache worden pas ongeldig wanneer de gebruiker zijn profiel bijwerkt.

In dit geval kan de cache de vermelding alleen verwijderen als het profielobject wordt verwijderd.

3.1. Data structuren

Laten we klassen maken om deze entiteiten te vertegenwoordigen.

We beginnen eerst met de gebruiker:

openbare klasse Gebruiker {lange privé-ID; private String naam; openbare gebruiker (lange id, tekenreeksnaam) {this.id = id; this.name = naam; } openbare lange getId () {retour-id; } public String getName () {retournaam; }}

Dan de sessie:

openbare klas Sessie {privé lange id; openbare sessie (lange id) {this.id = id; } openbare lange getId () {retour-id; }} 

En tot slot het profiel:

openbaar klasseprofiel {privé lange id; privé String-type; openbaar profiel (lange id, stringtype) {this.id = id; this.type = type; } openbare lange getId () {retour-id; } public String getName () {retourtype; }}

3.2. De caches maken

Laten we een instantie maken van ConcurrentMap voor de sessiecache met behulp van de makeMap methode:

ConcurrentMap sessionCache = nieuwe MapMaker (). MakeMap ();

De geretourneerde kaart staat geen null-waarden toe voor zowel de sleutel als de waarde.

Laten we nu nog een exemplaar maken van ConcurrentMap voor de profielcache:

ConcurrentMap profileCache = nieuwe MapMaker (). MakeMap ();

Merk op dat we de initiële capaciteit voor de caches niet hebben gespecificeerd. Zo,MapMaker maakt standaard een kaart met capaciteit 16.

Als we willen, kunnen we de capaciteit aanpassen met de initialCapacity methode:

ConcurrentMap profileCache = nieuwe MapMaker (). InitialCapacity (100) .makeMap ();

3.3. Het gelijktijdigheidsniveau wijzigen

MapMaker sets de standaardwaarde voor het gelijktijdigheidsniveau op 4. echter, de sessionCache moet een groter aantal gelijktijdige updates ondersteunen zonder enige discussie over discussies.

Hier de concurrencyLevel builder-methode komt te hulp:

ConcurrentMap sessionCache = nieuwe MapMaker (). ConcurrencyLevel (10) .makeMap ();

3.4. Zwakke referenties gebruiken

De kaarten die we hierboven hebben gemaakt, gebruiken sterke verwijzingen voor zowel de sleutels als de waarden. De vermeldingen blijven dus op de kaart, zelfs als de sleutels en de waarden worden opgehaald. We zouden in plaats daarvan zwakke referenties moeten gebruiken.

EEN sessionCache invoer is ongeldig nadat de sleutel (het gebruikersobject) is opgehaald. Laten we dus zwakke verwijzingen gebruiken voor de sleutels:

ConcurrentMap sessionCache = nieuwe MapMaker (). ZwakkeKeys (). MakeMap ();

Voor de profileCachekunnen we zwakke referenties gebruiken voor de waarden:

ConcurrentMap profileCache = nieuwe MapMaker (). ZwakkeValues ​​(). MakeMap ();

Wanneer deze referenties door huisvuil worden opgehaald, garandeert Guava dat deze inzendingen wordt niet opgenomen in een van de volgende lees- of schrijfbewerkingen op de kaart. echter, de grootte() De methode kan soms inconsistent zijn en deze kunnen bevatten inzendingen.

4. MapMaker Internals

MapMaker creëert een ConcurrentHashMap standaard als zwakke referenties niet zijn ingeschakeld. De gelijkheidscontroles gebeuren via de gebruikelijke gelijkwaardigheidsmethode.

Als we zwakke referenties inschakelen, dan MapMaker maakt een aangepaste kaart intern vertegenwoordigd door een set hashtabellen. Het deelt ook vergelijkbare prestatiekenmerken als een ConcurrentHashMap.

Wel een belangrijk verschil met WeakHashMap is dat de gelijkheidscontroles plaatsvinden via de identiteit (== en identityHashCode) vergelijkingen.

5. Conclusie

In dit korte artikel hebben we geleerd hoe we de MapMaker class om een ​​threadveilige kaart te maken. We hebben ook gezien hoe we de kaart kunnen aanpassen om zwakke referenties te gebruiken.

Zoals altijd is de volledige broncode van het artikel beschikbaar op GitHub.