Слаби референции в Java

1. Общ преглед

В тази статия ще разгледаме концепцията за слаба препратка - на езика Java.

Ще обясним какво представляват, за какво се използват и как да работим правилно с тях.

2. Слаби референции

Слабо препратен обект се изчиства от Събирача на боклук, когато е слабо достъпен.

Слабата достъпност означава, че обектът няма нито силни, нито меки препратки към него . До обекта може да се стигне само чрез обхождане на слаба препратка.

Първо, Garbage Collector изчиства слаба препратка, така че референтът вече не е достъпен. След това препратката се поставя в опашка за препратка (ако има свързана такава), откъдето можем да я получим.

В същото време ще бъдат финализирани преди това слабо достъпни обекти.

2.1. Слаби срещу меки референции

Понякога разликата между слаби и меки препратки е неясна. Меките препратки всъщност са голям LRU кеш. Тоест, ние използваме меки препратки, когато референтът има голям шанс да бъде използван повторно в близко бъдеще .

Тъй като меката препратка действа като кеш, тя може да продължи да бъде достъпна, дори ако самият референт не е. В интерес на истината меката референция е допустима за събиране само и само ако:

  • Референтът не е силно достъпен
  • Меката референция не е достъпна наскоро

Така че мека справка може да бъде достъпна за минути или дори часове след като референтът стане недостъпен. От друга страна, слаба справка ще бъде достъпна само докато нейният референт все още е наоколо.

3. Използвайте калъфи

Както се посочва в документацията за Java, най-често се използват слаби препратки за прилагане на канонизиращи картографирания . Картографирането се нарича канонизирано, ако съдържа само един екземпляр на определена стойност. Вместо да създава нов обект, той търси съществуващия в картографирането и го използва.

Разбира се, най-известен използването на тези справки е WeakHashMap класа . Това е изпълнението на интерфейса Map, където всеки ключ се съхранява като слаба препратка към дадения ключ. Когато Събирачът на боклук премахне ключ, обектът, свързан с този ключ, също се изтрива.

За повече информация вижте нашето ръководство за WeakHashMap.

Друга област, в която те могат да бъдат използвани, е проблемът с изслушания на изтъркани .

Издател (или тема) има силни препратки към всички абонати (или слушатели), за да ги уведомява за случили се събития. Проблемът възниква, когато слушател не може успешно да се отпише от издател.

Следователно слушателят не може да събира боклук, тъй като силна препратка към него все още е достъпна за издател. Следователно може да се случи изтичане на памет.

Решението на проблема може да бъде субект, който има слаба препратка към наблюдател, позволяващ на първия да се събира боклук, без да е необходимо да се отписва (имайте предвид, че това не е цялостно решение и въвежда някои други проблеми, които не са обхванати тук).

4. Работа със слаби референции

Слабите препратки са представени от класа java.lang.ref.WeakReference . Можем да го инициализираме, като предадем референт като параметър. По желание можем да предоставим java.lang.ref.ReferenceQueue :

Object referent = new Object(); ReferenceQueue referenceQueue = new ReferenceQueue(); WeakReference weakReference1 = new WeakReference(referent); WeakReference weakReference2 = new WeakReference(referent, referenceQueue); 

Референтът на препратка може да бъде извлечен чрез метода get и да бъде премахнат ръчно с помощта на метода clear :

Object referent2 = weakReference1.get(); weakReference1.clear(); 

Моделът за безопасна работа с този вид препратки е същият като при меките препратки:

Object referent3 = weakReference2.get(); if (referent3 != null) { // GC hasn't removed the instance yet } else { // GC has cleared the instance }

5. Заключение

В този бърз урок разгледахме концепцията за ниско ниво на слаба препратка в Java - и се фокусирахме върху най-често срещаните сценарии за използването им.