Розуміння довідкових класів Java: SoftReference, WeakReference та PhantomReference


81

Хтось може пояснити різницю між трьома довідковими класами (або опублікувати посилання на приємне пояснення)? SoftReference> WeakReference> PhantomReference, Але коли б я використовувати кожен з них? Чому є, WeakHashMapале ні SoftHashMapчи ні PhantomHashMap?

І якщо я використовую наступний код ...

WeakReference<String> ref = new WeakReference<String>("Hello!");
if (ref != null) {                 // ref can get collected at any time...
    System.gc();                   // Let's assume ref gets collected here.
    System.out.println(ref.get()); // Now what?!
}

...Що сталося? Повинен чи я , щоб перевірити, refє нулем перед кожним оператором (це не так, але то , що повинен я робити)? Вибачте за швидкі питання, але у мене проблеми з розумінням цих Referenceкласів ... Дякую!


1
Чому виникає, WeakHashMapале немає SoftHashMapабо PhantomHashMapчудове запитання, чому я цього раніше не помічав .. ??
Мехрадж Малік,

1
ref != nullПеревірка не має сенсу. refніколи не буде null.
Holger

додавання до Q: strongRef --> weakRef --> objA. Тепер буде objAGCed чи ні, оскільки це непряме посилання від strongRef.
samshers

Відповіді:


60

Документація бібліотеки Java для java.lang.refпакету характеризує зменшення сили трьох явних типів посилань.

Ви використовуєте, SoftReferenceколи ви хочете, щоб об'єкт, на який посилається, залишався живим, поки в хості не закінчиться обсяг пам'яті. Об’єкт не буде придатним для збору, доки колектору не буде потрібно звільнити пам’ять. Вільно висловлене, прив'язуючи SoftReferenceзасіб: "Закріпіть об'єкт, доки більше не зможете".

Навпаки, використовуйте a, WeakReferenceколи ви не хочете впливати на час життя об’єкта, на який посилається; ви просто хочете зробити окреме твердження про об’єкт, на який посилається, поки він залишається живим. На придатність об’єкта до збору не впливає наявність пов’язаних WeakReferences. Щось на зразок зовнішнього зіставлення з екземпляра об'єкта на пов'язану властивість, де властивість потрібно реєструвати лише доти, доки пов'язаний об'єкт живе, є хорошим використанням для WeakReferences і WeakHashMap.

Останній PhantomReference- важче охарактеризувати. Мовляв WeakReference, такий зв’язок PhantomReferenceне впливає на життя об’єкта, на який посилається. Але на відміну від інших еталонних типів, неможливо навіть розпізнати a PhantomReference. У певному сенсі це не вказує на те, на що вказує, наскільки можуть зрозуміти абоненти. Це просто дозволяє асоціювати деякі пов'язані дані з об'єктом, на який посилається - дані, які згодом можуть бути перевірені та реагувати на них, коли PhantomReferenceчерги потрапляють у відповідний зв’язок ReferenceQueue. Зазвичай один отримує тип із PhantomReferenceі включає деякі додаткові дані в цей похідний тип. На жаль, для використання такого похідного типу задіяно деяке зниження.

У вашому прикладі коду refнуль не може бути посиланням (або, якщо ви бажаєте, "змінною"). Швидше, це значення, отримане при виклику Reference#get(), може бути нульовим. Якщо воно виявиться нульовим, ви запізнилися; об’єкт, на який посилається, вже на шляху до збору:

final String val = ref.get();
if (null != val)
{
  // "val" is now pinned strongly.
}
else
{
  // "val" is already ready to be collected.
}

додавання до Q: strongRef --> weakRef --> objA. Тепер буде objAGCed чи ні, оскільки це непряме посилання від strongRef.
samshers

Якщо я правильно розумію ваше запитання, @samshers objAможе брати участь у зборі як сміття. Закріплення WeakReferenceаеру не впливає на об'єкт, на який це WeakReferenceвказує.
seh

Не має сильної посилання вгору по ланцюжку, це робить різницю. Тому що для того, objAщоб збирати сміття, слабке посилання потрібно видалити спочатку праворуч. І сильне посилання вказує на слабке посилання, що робить слабкого рефера
недоступним

Ні, WeakReferenceне потрібно збирати, щоб дозволити objAзбирати. WeakReferenceЧи не тримає в objAживих. Швидше, це спосіб знайти, objAпоки він живий - не впливаючи на це життя - і виявити, коли колектор вже забрав його.
seh

6

Посилання: https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

PhantomHashMapне буде працювати дуже добре, як getзавжди повертається nullдля фантомних посилань.

Кеші важкі, тому SoftHashMapможуть працювати не так добре, як ви думаєте. Однак я вважаю, що бібліотека колекцій Google містить загальну довідкову карту.

Завжди слід перевіряти, чи getповертається не- null. (Зверніть увагу, що не перевіряючи, що саме Referenceпосилання не є null.) У випадку інтернованих рядків це буде завжди, але (як ніколи) не намагайтеся бути "розумним" щодо цього.


Термін дії посилання закінчився.
Mehraj Malik

Виправлено посилання @MehrajMalik.
Том Хоутін - таклін

додавання до Q: strongRef --> weakRef --> objA. Тепер буде objAGCed чи ні, оскільки це непряме посилання від strongRef.
samshers


0
String str = new String("hello, world");
WeakReference<String> ref = new WeakReference<String>(str);
str = null;

if (ref != null) {                 
    System.gc(); 
    System.out.println(ref.get());
}

У цьому випадку він виведе нуль. Тут System.gc()важливий заклик до .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.