Розуміння довідкових класів 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.