Vejledning til WeakHashMap i Java

1. Oversigt

I denne artikel vil vi se på en WeakHashMap fra java.util pakke.

For at forstå datastrukturen bruger vi den her til at udrulle en simpel cacheimplementering. Husk dog, at dette er meningen at forstå, hvordan kortet fungerer, og det er næsten altid en dårlig idé at oprette din egen cacheimplementering.

Kort sagt, den WeakHashMap er en hashtable-baseret implementering af Kort interface med taster, der er af en Svag henvisning type.

En post i en WeakHashMap fjernes automatisk, når nøglen ikke længere er i almindelig brug, hvilket betyder, at der ikke er nogen enkelt Reference det peger på den nøgle. Når skraldopsamlingsprocessen (GC) kasserer en nøgle, fjernes dens indtastning effektivt fra kortet, så denne klasse opfører sig noget anderledes end andre Kort implementeringer.

2. Stærke, bløde og svage referencer

At forstå, hvordan WeakHashMap arbejder, vi er nødt til at se på en Svag henvisning klasse - som er den grundlæggende konstruktion for nøgler i WeakHashMap implementering. I Java har vi tre hovedtyper af referencer, som vi forklarer i de følgende afsnit.

2.1. Stærke referencer

Den stærke reference er den mest almindelige type Reference som vi bruger i vores daglige programmering:

Heltals prime = 1;

Variablen prime har en stærk reference til en Heltal objekt med værdi 1. Ethvert objekt, der har en stærk reference, der peger på det, er ikke berettiget til GC.

2.2. Bløde referencer

Kort sagt, et objekt, der har en SoftReference at pege på det bliver ikke affald indsamlet, før JVM absolut har brug for hukommelse.

Lad os se, hvordan vi kan oprette en SoftReference i Java:

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

Det prime objekt har en stærk reference, der peger på det.

Dernæst pakker vi ind prime stærk reference til en blød reference. Efter at have foretaget den stærke reference nul, a prime objekt er berettiget til GC, men indsamles kun, når JVM absolut har brug for hukommelse.

2.3. Svage referencer

De objekter, der kun refereres til ved svage referencer, er skrald opsamlet ivrigt; GC venter ikke, indtil den har brug for hukommelse i så fald.

Vi kan oprette en Svag henvisning i Java på følgende måde:

Heltals prime = 1; WeakReference soft = ny WeakReference (prime); prime = null;

Da vi lavede en prime reference nul, det prime objekt vil blive indsamlet skrald i den næste GC-cyklus, da der ikke er nogen anden stærk reference, der peger på den.

Henvisninger til en Svag henvisning bruges som nøgler i WeakHashMap.

3. WeakHashMap som en effektiv hukommelsescache

Lad os sige, at vi vil opbygge en cache, der holder store billedobjekter som værdier og billednavne som nøgler. Vi ønsker at vælge en korrekt kortimplementering til løsning af dette problem.

Brug af en simpel HashMap vil ikke være et godt valg, fordi værdien objekter kan optage en masse hukommelse. Hvad mere er, vil de aldrig blive genvundet fra cachen ved en GC-proces, selv når de ikke længere er i brug i vores applikation.

Ideelt set ønsker vi en Kort implementering, der gør det muligt for GC automatisk at slette ubrugte objekter. Når en nøgle til et stort billedobjekt ikke bruges i vores applikation noget sted, slettes denne post fra hukommelsen.

Heldigvis er WeakHashMap har nøjagtigt disse egenskaber. Lad os teste vores WeakHashMap og se hvordan det opfører sig:

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

Vi opretter en WeakHashMap eksempel, der gemmer vores BigImage genstande. Vi lægger en BigImage objekt som en værdi og en imageName objektreference som en nøgle. Det imageName gemmes på et kort som en Svag henvisning type.

Dernæst indstiller vi imageName henvisning til at være nulderfor er der ikke flere referencer, der peger på storbillede objekt. Standardadfærden for a WeakHashMap er at genvinde en post, der ikke har nogen henvisning til den ved næste GC, så denne post slettes fra hukommelsen ved den næste GC-proces.

Vi kalder en System.gc () for at tvinge JVM til at udløse en GC-proces. Efter GC-cyklussen, vores WeakHashMap vil være tom:

WeakHashMap-kort = nyt WeakHashMap (); BigImage bigImageFirst = ny BigImage ("foo"); UniqueImageName imageNameFirst = nyt UniqueImageName ("name_of_big_image"); BigImage bigImageSecond = ny BigImage ("foo_2"); UniqueImageName imageNameSecond = nyt 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 (); afvente (). atMost (10, TimeUnit.SECONDS) .tiltil (() -> kort.størrelse () == 1); afventer (). atMost (10, TimeUnit.SECONDS) .tiltil (() -> map.containsKey (imageNameSecond));

Bemærk, at kun imageNameFirst reference er indstillet til nul. Det imageNameSecond reference forbliver uændret. Når GC er udløst, vil kortet kun indeholde en post - imageNameSecond.

4. Konklusion

I denne artikel kiggede vi på typer referencer i Java for fuldt ud at forstå, hvordan java.util.WeakHashMap arbejder. Vi oprettede en simpel cache, der udnytter en adfærd WeakHashMap og test om det fungerer som forventet.

Implementeringen af ​​alle disse eksempler og kodestykker findes i GitHub-projektet - som er et Maven-projekt, så det skal være let at importere og køre som det er.