Vodič za WeakHashMap u Javi

1. Pregled

U ovom ćemo članku pogledati WeakHashMap od java.util paket.

Da bismo razumjeli strukturu podataka, ovdje ćemo je koristiti za uvođenje jednostavne predmemorije. Međutim, imajte na umu da je ovo namijenjeno razumijevanju načina rada mape, a stvaranje vlastite implementacije predmemorije gotovo je uvijek loša ideja.

Jednostavno rečeno, WeakHashMap je provedba programa temeljenog na raspršivanju Karta sučelje, s tipkama koje su od Slaba referenca tip.

Unos u a WeakHashMap automatski će se ukloniti kada njegov ključ više nije u uobičajenoj upotrebi, što znači da ne postoji niti jedan Referenca ta točka na taj ključ. Kada postupak prikupljanja smeća (GC) odbaci ključ, njegov se unos učinkovito uklanja s karte, pa se ova klasa ponaša ponešto drugačije od ostalih Karta implementacije.

2. Jake, meke i slabe reference

Da bih razumio kako WeakHashMap djela, moramo pogledati a Slaba referenca razred - što je osnovna konstrukcija za ključeve u WeakHashMap provedba. U Javi imamo tri glavne vrste referenci, koje ćemo objasniti u sljedećim odjeljcima.

2.1. Jake reference

Snažna referenca je najčešći tip Referenca koje koristimo u svakodnevnom programiranju:

Cijeli broj prost = 1;

Varijabla premijera ima jaka referenca do an Cijeli broj objekt s vrijednošću 1. Bilo koji objekt koji ima snažnu referencu na njega ne ispunjava uvjete za GC.

2.2. Meke reference

Jednostavno rečeno, objekt koji ima SoftReference ukazujući na to da se neće sakupljati smeće dok JVM-u apsolutno ne bude potrebna memorija.

Pogledajmo kako možemo stvoriti SoftReference na Javi:

Cijeli broj prost = 1; SoftReference soft = novi SoftReference (glavni); prime = null;

The premijera objekt ima snažnu referencu koja upućuje na njega.

Dalje, omatamo premijera jaka referenca u meku referencu. Nakon te snažne reference null, a premijera objekt ispunjava uvjete za GC, ali bit će prikupljen samo kad JVM-u apsolutno treba memorija.

2.3. Slabe reference

Objekti na koje se pozivaju samo slabe reference smeće se nestrpljivo sakuplja; GC neće čekati dok mu u tom slučaju ne bude potrebna memorija.

Možemo stvoriti Slaba referenca u Javi na sljedeći način:

Cijeli broj prost = 1; WeakReference soft = novo WeakReference (osnovno); prime = null;

Kad smo napravili premijera referenca null, premijera objekt će biti smeće prikupljeno u sljedećem GC ciklusu, jer na njega ne postoji druga jaka referenca.

Reference a Slaba referenca tipa koriste se kao tipke u WeakHashMap.

3. WeakHashMap kao učinkovita memorijska predmemorija

Recimo da želimo izgraditi predmemoriju koja velike slikovne objekte čuva kao vrijednosti, a imena slika kao ključeve. Želimo odabrati odgovarajuću implementaciju mape za rješavanje tog problema.

Koristeći jednostavan HashMap neće biti dobar izbor jer vrijednosni objekti mogu zauzimati puno memorije. Štoviše, oni nikada neće biti vraćeni iz predmemorije pomoću GC postupka, čak i ako se više ne koriste u našoj aplikaciji.

U idealnom slučaju, želimo Karta implementacija koja omogućuje GC-u da automatski briše neiskorištene objekte. Kada se ključ velikog slikovnog objekta ni u jednom mjestu ne koristi u našoj aplikaciji, taj će se unos izbrisati iz memorije.

Srećom, WeakHashMap ima upravo ove karakteristike. Isprobajmo svoje WeakHashMap i pogledajte kako se ponaša:

WeakHashMap karta = nova WeakHashMap (); BigImage bigImage = nova BigImage ("image_id"); UniqueImageName imageName = novo UniqueImageName ("name_of_big_image"); map.put (imageName, bigImage); assertTrue (map.containsKey (imageName)); imageName = null; System.gc (); await (). atMost (10, TimeUnit.SECONDS) .until (map :: isEmpty);

Stvaramo a WeakHashMap instanci koja će pohraniti naš BigImage predmeta. Stavljamo BigImage objekt kao vrijednost i an imageName referenca na objekt kao ključ. The imageName bit će pohranjeni na karti kao Slaba referenca tip.

Dalje, postavljamo imageName referenca biti null, stoga više nema referenci koje upućuju na bigImage objekt. Zadano ponašanje a WeakHashMap je povrat zahtjeva za unos koji na njega nema referencu na sljedećem GC-u, pa će ovaj unos biti izbrisan iz memorije sljedećim GC postupkom.

Zovemo a System.gc () prisiliti JVM da pokrene GC postupak. Nakon GC ciklusa, naš WeakHashMap bit će prazno:

WeakHashMap karta = nova WeakHashMap (); BigImage bigImageFirst = novi BigImage ("foo"); UniqueImageName imageNameFirst = novo UniqueImageName ("name_of_big_image"); BigImage bigImageSecond = novi BigImage ("foo_2"); UniqueImageName imageNameSecond = novo 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));

Imajte na umu da samo imageNameFirst referenca je postavljena na null. The imageNameSecond referenca ostaje nepromijenjena. Nakon pokretanja GC, karta će sadržavati samo jedan unos - imageNameSecond.

4. Zaključak

U ovom smo članku pregledali vrste referenci u Javi kako bismo u potpunosti razumjeli kako java.util.WeakHashMap djela. Stvorili smo jednostavnu predmemoriju koja koristi ponašanje a WeakHashMap i testirajte radi li kako smo očekivali.

Provedbu svih ovih primjera i isječaka koda možete pronaći u projektu GitHub - koji je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.