Sprievodca po WeakHashMap v Jave

1. Prehľad

V tomto článku sa pozrieme na WeakHashMap z java.util balíček.

Aby sme pochopili dátovú štruktúru, použijeme ju tu na zavedenie jednoduchej implementácie vyrovnávacej pamäte. Nezabúdajte však, že to má pochopiť, ako mapa funguje, a vytvorenie vlastnej implementácie vyrovnávacej pamäte je takmer vždy zlý nápad.

Jednoducho povedané WeakHashMap je implementácia Mapa rozhranie s kľúčmi, ktoré sú z a Slabá referencia typu.

Záznam v a WeakHashMap bude automaticky odstránený, keď už jeho kľúč nebude bežne používaný, čo znamená, že neexistuje žiaden Odkaz ten bod na ten kľúč. Keď proces zhromažďovania odpadu (GC) odhodí kľúč, jeho položka sa účinne odstráni z mapy, takže táto trieda sa chová trochu odlišne od ostatných Mapa implementácie.

2. Silné, mäkké a slabé referencie

Aby sme pochopili, ako WeakHashMap Tvorba, musíme sa pozrieť na a Slabá referencia trieda Windows - ktorý je základnou konštrukciou pre kľúče v systéme Windows - WeakHashMap implementácia. V prostredí Java máme tri hlavné typy odkazov, ktoré si vysvetlíme v nasledujúcich častiach.

2.1. Silné odkazy

Silná referencia je najbežnejším typom Odkaz ktoré používame pri každodennom programovaní:

Celé číslo prime = 1;

Premenná hlavnýsilná referencia do an Celé číslo objekt s hodnotou 1. Akýkoľvek objekt, ktorý na ňu smeruje silným odkazom, nie je oprávnený na GC.

2.2. Mäkké referencie

Jednoducho povedané, objekt, ktorý má a SoftReference ukazujúci na to nebude zbierať odpadky, kým JVM absolútne nebude potrebovať pamäť.

Pozrime sa, ako môžeme vytvoriť SoftReference v Jave:

Celé číslo prime = 1; SoftReference soft = nový SoftReference (prime); prime = null;

The hlavný objekt má silný odkaz smerujúci k nemu.

Ďalej balíme hlavný silná referencia do mäkkej referencie. Po vykonaní tohto silného odkazu nulový, a hlavný objekt je vhodný pre GC, ale bude zhromaždený, iba keď JVM nevyhnutne potrebuje pamäť.

2.3. Slabé referencie

Objekty, na ktoré odkazujú iba slabé odkazy, sú dychtivo zhromažďované; GC nebude v takom prípade čakať, kým nebude potrebovať pamäť.

Môžeme vytvoriť Slabá referencia v jazyku Java nasledujúcim spôsobom:

Celé číslo prime = 1; WeakReference soft = nový WeakReference (prime); prime = null;

Keď sme vyrobili a hlavný odkaz nulový, hlavný objekt bude zhromažďovaný v ďalšom cykle GC, pretože na neho neukazuje žiadny iný silný odkaz.

Referencie a Slabá referencia typu sa používajú ako kľúče v WeakHashMap.

3. WeakHashMap ako efektívna pamäť cache

Povedzme, že chceme vytvoriť medzipamäť, ktorá uchová veľké obrazové objekty ako hodnoty a názvy obrázkov ako kľúče. Chceme zvoliť správnu implementáciu mapy na riešenie tohto problému.

Pomocou jednoduchého HashMap nebude dobrá voľba, pretože hodnotové objekty môžu zaberať veľa pamäte. A čo viac, nikdy ich nebude proces GC získavať z medzipamäte, aj keď sa už v našej aplikácii nepoužívajú.

Ideálne je, ak chceme a Mapa implementácia, ktorá umožňuje spoločnosti GC automaticky mazať nepoužívané objekty. Keď sa kľúč veľkého obrázkového objektu v našej aplikácii na akomkoľvek mieste nepoužíva, táto položka bude vymazaná z pamäte.

Našťastie WeakHashMap má presne tieto vlastnosti. Poďme vyskúšať WeakHashMap a uvidíte, ako sa chová:

Mapa WeakHashMap = nová WeakHashMap (); BigImage bigImage = nový BigImage ("image_id"); UniqueImageName imageName = nový UniqueImageName ("name_of_big_image"); map.put (imageName, bigImage); assertTrue (map.containsKey (imageName)); imageName = null; System.gc (); await (). atMost (10, TimeUnit.SECONDS) .until (mapa :: isEmpty);

Vytvárame WeakHashMap inštancia, ktorá uloží naše BigImage predmety. Dávame a BigImage objekt ako hodnota a imageName odkaz na objekt ako kľúč. The imageName budú uložené na mape ako a Slabá referencia typu.

Ďalej nastavíme imageName odkaz na nulový, preto už neexistujú žiadne odkazy smerujúce k bigImage objekt. Predvolené správanie a WeakHashMap je získať späť položku, ktorá na ňu nemá odkaz na ďalšom GC, takže táto položka bude odstránená z pamäte ďalším procesom GC.

Voláme a System.gc () prinútiť JVM spustiť proces GC. Po cykle GC náš WeakHashMap bude prázdny:

Mapa WeakHashMap = nová WeakHashMap (); BigImage bigImageFirst = nový BigImage ("foo"); UniqueImageName imageNameFirst = nový UniqueImageName ("name_of_big_image"); BigImage bigImageSecond = nový BigImage ("foo_2"); UniqueImageName imageNameSecond = nový 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 (); await (). atMost (10, TimeUnit.SECONDS) .until (() -> map.size () == 1); await (). atMost (10, TimeUnit.SECONDS) .until (() -> map.containsKey (imageNameSecond));

Upozorňujeme, že iba imageNameFirst odkaz je nastavený na nulový. The imageNameSecond referencia zostáva nezmenená. Po spustení GC bude mapa obsahovať iba jeden záznam - imageNameSecond.

4. Záver

V tomto článku sme sa pozreli na typy odkazov v Jave, aby sme úplne pochopili ako java.util.WeakHashMap Tvorba. Vytvorili sme jednoduchú vyrovnávaciu pamäť, ktorá využíva správanie a WeakHashMap a otestujte, či funguje tak, ako sme očakávali.

Implementáciu všetkých týchto príkladov a útržkov kódu nájdete v projekte GitHub - čo je projekt Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.


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