Útmutató a Java WeakHashMap programhoz

1. Áttekintés

Ebben a cikkben megvizsgáljuk a WeakHashMap tól java.util csomag.

Az adatszerkezet megértése érdekében itt fogjuk használni egy egyszerű gyorsítótár-megvalósítás bevezetését. Ne feledje azonban, hogy ez a térkép működésének megértésére szolgál, és saját gyorsítótár-megvalósításának létrehozása szinte mindig rossz ötlet.

Egyszerűen fogalmazva: WeakHashMap hashtable-alapú megvalósítása a Térkép felület, olyan kulcsokkal, amelyek a WeakReference típus.

Bejegyzés a WeakHashMap automatikusan eltávolításra kerül, ha a kulcsa már nem a szokásos használatban van, ami azt jelenti, hogy nincs egyetlen Referencia hogy arra a kulcsra mutat. Amikor a szemétgyűjtési (GC) folyamat eldob egy kulcsot, akkor annak beírása gyakorlatilag eltávolításra kerül a térképről, így ez az osztály némileg másként viselkedik, mint a többi Térkép megvalósítások.

2. Erős, puha és gyenge hivatkozások

Megérteni, hogy a WeakHashMap művek, meg kell néznünk a WeakReference osztály - amely a kulcsok alapvető konstrukciója a WeakHashMap végrehajtás. A Java-ban három fő hivatkozási típusunk van, amelyeket a következő szakaszokban ismertetünk.

2.1. Erős hivatkozások

Az erős referencia a leggyakoribb típus Referencia amelyet a napi programozás során használunk:

Egész prím = 1;

A változó elsődleges van egy erős referencia egy Egész szám objektum, amelynek értéke 1. Bármely objektum, amelyre erős hivatkozás van, nem jogosult a GC-re.

2.2. Lágy hivatkozások

Egyszerűen fogalmazva: egy tárgy, amelynek van SoftReference rámutatva, hogy nem lesz szemét, amíg a JVM-nek feltétlenül szüksége van memóriára.

Lássuk, hogyan hozhatunk létre a SoftReference Java-ban:

Egész prím = 1; SoftReference soft = új SoftReference (elsődleges); prím = null;

A elsődleges az objektumnak erős hivatkozása van rá.

Ezután csomagolunk elsődleges erős referencia puha referenciává. Miután ezt az erős utalást tette nulla, a elsődleges Az objektum jogosult a GC használatára, de csak akkor gyűjtjük, amikor a JVM-nek feltétlenül szüksége van memóriára.

2.3. Gyenge hivatkozások

Azok az objektumok, amelyekre csak gyenge hivatkozások hivatkoznak, lelkesen gyűjtenek szemetet; a GC ebben az esetben nem várja meg, amíg szüksége lesz memóriára.

Hozhatunk létre a WeakReference Java-ban a következő módon:

Egész prím = 1; WeakReference soft = new WeakReference (prime); prím = null;

Amikor elkészítettük a elsődleges referencia nulla, a elsődleges az objektum a következő GC ciklusban gyűjtött szemét lesz, mivel nincs más, erre utaló erős referencia.

Hivatkozások a WeakReference típusú kulcsokat használják a WeakHashMap.

3. WeakHashMap mint hatékony memória gyorsítótár

Tegyük fel, hogy ki akarunk építeni egy gyorsítótárat, amely a nagy képobjektumokat értékként, a képneveket pedig kulcsként tartja. Megfelelő térkép-megvalósítást szeretnénk választani a probléma megoldására.

Egy egyszerű használatával HashMap nem lesz jó választás, mert az értékobjektumok sok memóriát foglalhatnak el. Sőt, soha nem kapja meg őket a gyorsítótárból egy GC-folyamat, még akkor sem, ha már nem használják őket az alkalmazásunkban.

Ideális esetben a Térkép megvalósítás, amely lehetővé teszi a GC számára a fel nem használt objektumok automatikus törlését. Ha egy nagy kép objektum kulcsát semmilyen helyen nem használjuk alkalmazásunkban, akkor a bejegyzés törlődik a memóriából.

Szerencsére a WeakHashMap pontosan ezek a jellemzői vannak. Teszteljük a mi WeakHashMap és nézze meg, hogyan viselkedik:

WeakHashMap map = új WeakHashMap (); BigImage bigImage = új BigImage ("image_id"); UniqueImageName imageName = új UniqueImageName ("nagy_kép_neve"); map.put (imageName, bigImage); assertTrue (map.containsKey (imageName)); imageName = null; System.gc (); várjon (). atMost (10, TimeUnit.SECONDS). amíg (map :: isEmpty);

Készítünk egy WeakHashMap példány, amely tárolja a mi BigImage tárgyakat. A BigImage objektum mint érték és egy imageName objektum hivatkozás kulcsként. A imageName a térképen a-ként tárolódik WeakReference típus.

Ezután beállítjuk a imageName hivatkozás arra nulla, ezért nincs több utalás a bigImage tárgy. Az a alapértelmezett viselkedése WeakHashMap egy olyan bejegyzés visszakérése, amelyre nincs utalás a következő GC-n, ezért a következő GC folyamat ezt a bejegyzést törli a memóriából.

Hívjuk a System.gc () arra kényszeríteni a JVM-et, hogy indítson egy GC folyamatot. A GC ciklus után a mi WeakHashMap üres lesz:

WeakHashMap map = új WeakHashMap (); BigImage bigImageFirst = új BigImage ("foo"); UniqueImageName imageNameFirst = új UniqueImageName ("nagy_kép_neve"); BigImage bigImageSecond = új BigImage ("foo_2"); UniqueImageName imageNameSecond = új UniqueImageName ("nagy_kép_neve__neve"); map.put (imageNameFirst, bigImageFirst); map.put (imageNameSecond, bigImageSecond); assertTrue (map.containsKey (imageNameFirst)); assertTrue (map.containsKey (imageNameSecond)); imageNameFirst = null; System.gc (); várjon (). atMost (10, TimeUnit.SECONDS). amíg (() -> map.size () == 1); várjon (). atMost (10, TimeUnit.SECONDS). (() -> map.containsKey (imageNameSecond));

Vegye figyelembe, hogy csak a imageNameFirst a hivatkozás értéke nulla. A imageNameSecond referencia változatlan marad. A GC aktiválása után a térkép csak egy bejegyzést tartalmaz - imageNameSecond.

4. Következtetés

Ebben a cikkben megvizsgáltuk a Java-ban található hivatkozások típusait, hogy teljes mértékben megértsük, hogyan java.util.WeakHashMap művek. Hoztunk létre egy egyszerű gyorsítótárat, amely kihasználja az a viselkedését WeakHashMap és tesztelje, hogy a várt módon működik-e.

Ezeknek a példáknak és kódrészleteknek a megvalósítása megtalálható a GitHub projektben - amely egy Maven projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.