Guide til WeakHashMap i Java

1. Oversikt

I denne artikkelen vil vi se på a WeakHashMap fra java.util pakke.

For å forstå datastrukturen, bruker vi den her for å rulle ut en enkel cacheimplementering. Husk imidlertid at dette er ment for å forstå hvordan kartet fungerer, og å lage din egen cacheimplementering er nesten alltid en dårlig idé.

Enkelt sagt, den WeakHashMap er en hashtable-basert implementering av Kart grensesnitt, med nøkler som er av en Svak referanse type.

En oppføring i en WeakHashMap vil automatisk bli fjernet når nøkkelen ikke lenger er i vanlig bruk, noe som betyr at det ikke er en enkelt Henvisning som peker på den nøkkelen. Når søppeloppsamlingsprosessen (GC) kaster en nøkkel, blir innføringen effektivt fjernet fra kartet, så denne klassen oppfører seg noe annerledes enn andre Kart implementeringer.

2. Sterke, myke og svake referanser

For å forstå hvordan WeakHashMap virker, vi må se på en Svak referanse klasse - som er den grunnleggende konstruksjonen for nøkler i WeakHashMap gjennomføring. I Java har vi tre hovedtyper av referanser, som vi vil forklare i de følgende avsnittene.

2.1. Sterke referanser

Den sterke referansen er den vanligste typen Henvisning som vi bruker i vår daglige programmering:

Heltall prime = 1;

Variabelen prime har en sterk referanse til en Heltall objekt med verdi 1. Ethvert objekt som har en sterk referanse som peker på det, er ikke kvalifisert for GC.

2.2. Myke referanser

Enkelt sagt, et objekt som har en SoftReference å peke på det blir ikke søppel samlet før JVM absolutt trenger minne.

La oss se hvordan vi kan lage en SoftReference i Java:

Heltall prime = 1; SoftReference soft = ny SoftReference (prime); prime = null;

De prime objektet har en sterk referanse som peker mot det.

Deretter pakker vi inn prime sterk referanse til en myk referanse. Etter å ha gjort den sterke referansen null, a prime objektet er kvalifisert for GC, men vil bare bli samlet når JVM absolutt trenger minne.

2.3. Svake referanser

Objektene som bare refereres til av svake referanser, blir søppel samlet ivrig; GC vil ikke vente til den trenger minne i så fall.

Vi kan lage en Svak referanse i Java på følgende måte:

Heltall prime = 1; WeakReference soft = new WeakReference (prime); prime = null;

Da vi laget en prime henvisning null, den prime gjenstand blir søppel samlet i neste GC-syklus, ettersom det ikke er noen annen sterk referanse som peker mot den.

Referanser til a Svak referanse brukes som nøkler i WeakHashMap.

3. WeakHashMap som en effektiv minnebuffer

La oss si at vi ønsker å bygge en cache som holder store bildeobjekter som verdier, og bildenavn som nøkler. Vi ønsker å velge en riktig kartimplementering for å løse det problemet.

Ved hjelp av en enkel HashMap vil ikke være et godt valg fordi verdiobjektene kan oppta mye minne. Dessuten vil de aldri bli gjenvunnet fra hurtigbufferen ved en GC-prosess, selv når de ikke lenger er i bruk i applikasjonen vår.

Ideelt sett ønsker vi en Kart implementering som gjør at GC automatisk kan slette ubrukte objekter. Når en nøkkel til et stort bildeobjekt ikke er i bruk i applikasjonen vår noe sted, vil denne oppføringen bli slettet fra minnet.

Heldigvis, den WeakHashMap har akkurat disse egenskapene. La oss teste vår WeakHashMap og se hvordan den oppfører seg:

WeakHashMap-kart = nytt WeakHashMap (); BigImage bigImage = ny BigImage ("image_id"); UniqueImageName imageName = new UniqueImageName ("name_of_big_image"); map.put (imageName, bigImage); assertTrue (map.containsKey (imageName)); imageName = null; System.gc (); avvente (). atMost (10, TimeUnit.SECONDS) .tiltil (kart :: er tom);

Vi lager en WeakHashMap forekomst som vil lagre vår BigImage gjenstander. Vi setter en BigImage objekt som en verdi og en imageName objektreferanse som en nøkkel. De imageName vil bli lagret på et kart som en Svak referanse type.

Deretter setter vi imageName referanse til å være null, derfor er det ikke flere referanser som peker til bigImage gjenstand. Standard oppførsel av a WeakHashMap er å gjenvinne en oppføring som ikke har referanse til den i neste GC, så denne oppføringen vil bli slettet fra minnet ved neste GC-prosess.

Vi kaller en System.gc () for å tvinge JVM til å utløse en GC-prosess. Etter GC-syklusen, vår WeakHashMap vil være tom:

WeakHashMap-kart = nytt WeakHashMap (); BigImage bigImageFirst = ny BigImage ("foo"); UniqueImageName imageNameFirst = ny UniqueImageName ("name_of_big_image"); BigImage bigImageSecond = ny BigImage ("foo_2"); UniqueImageName imageNameSecond = ny UniqueImageName ("name_of_big_image_2"); map.put (imageNameFirst, bigImageFirst); map.put (imageNameSecond, bigImageSecond); assertTrue (map.containsKey (imageNameFirst)); assertTrue (map.containsKey (imageNameSecond)); imageNameFirst = null; System.gc (); avvente (). atMost (10, TimeUnit.SECONDS) .tiltil (() -> map.størrelse () == 1); avvente (). atMost (10, TimeUnit.SECONDS) .tiltil (() -> map.containsKey (imageNameSecond));

Merk at bare imageNameFirst referanse er satt til null. De imageNameSecond referanse forblir uendret. Etter at GC er utløst, vil kartet bare inneholde en oppføring - imageNameSecond.

4. Konklusjon

I denne artikkelen så vi på typer referanser i Java for å forstå hvordan java.util.WeakHashMap virker. Vi opprettet en enkel cache som utnytter oppførselen til en WeakHashMap og test om det fungerer som vi forventet.

Implementeringen av alle disse eksemplene og kodebitene finnes i GitHub-prosjektet - som er et Maven-prosjekt, så det skal være enkelt å importere og kjøre som det er.


$config[zx-auto] not found$config[zx-overlay] not found