Использование Java ReferenceQueue - программирование

Использование Java ReferenceQueue

Do SoftReference и WeakReference действительно помогают только при создании в качестве переменных экземпляра? Есть ли какая-либо польза для их использования в области методов?

Другая большая часть - ReferenceQueue. Помимо возможности отслеживать, какие ссылки определяются мусором, может ли Reference.enqueue() использоваться для принудительной регистрации объекта для сбора мусора?

Например, было бы целесообразно создать метод, который забирает некоторые тяжелые ресурсы памяти (содержащие сильные ссылки) в объекте и создает ссылки для их размещения в очереди?

Object bigObject;
public void dispose() {
    ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
    WeakReference<Object> ref = new WeakReference<Object>(bigObject, queue);
    bigObject = null;
    ref.enqueue();
}

(Представьте, что Object в этом случае представляет тип объекта, который использует много памяти... например BufferedImage или что-то еще)

Имеет ли это какой-либо реалистичный эффект? Или это просто пустая трата кода?

4b9b3361

Ответ 1

Одна общая идиома со ссылочными очередями - например, подкласс WeakReference, чтобы прикрепить информацию, необходимую для очистки вещей, а затем опросить ReferenceQueue, чтобы выполнить задачи очистки.

ReferenceQueue<Foo> fooQueue = new ReferenceQueue<Foo>();

class ReferenceWithCleanup extends WeakReference<Foo> {
  Bar bar;
  ReferenceWithCleanup(Foo foo, Bar bar) {
    super(foo, fooQueue);
    this.bar = bar;
  }
  public void cleanUp() {
    bar.cleanUp();
  }
}

public Thread cleanupThread = new Thread() {
  public void run() {
    while(true) {
      ReferenceWithCleanup ref = (ReferenceWithCleanup)fooQueue.remove();
      ref.cleanUp();
    }
  }
}

public void doStuff() {
  cleanupThread.start();
  Foo foo = new Foo();
  Bar bar = new Bar();
  ReferenceWithCleanup ref = new ReferenceWithCleanup(foo, bar);
  ... // From now on, once you release all non-weak references to foo,
      // then at some indeterminate point in the future, bar.cleanUp() will
      // be run. You can force it by calling ref.enqueue().
}

Например, внутренности реализации Guava CacheBuilder, когда weakKeys выбраны использует этот подход.

Ответ 2

Если объект имеет только WeakReference (или никаких ссылок вообще!) по отношению к нему, это может быть сбор мусора, когда Java нужно сделать больше места в памяти. Таким образом, вы используете WeakReference всякий раз, когда вы хотите, чтобы объект оставался в памяти, но вам не нужно, чтобы он оставался ЧТО-то плохо (например, если Java должен мусорить его собирать, нет проблем, вы можете как-нибудь вернуть его и среднее время Java имеет лучшую производительность)

Завершение a WeakReference позволяет выполнить итерацию ReferenceQueue и определить, какие ссылки были собраны мусором, а какие нет. Это все - так сделайте это, только если вам нужно это знать.

Подробнее: http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

Ответ 3

Одна общая задача - создать карты мягких ссылок.

Map<String, SoftReference<BigThing>> cache = new HashMap<>();
Set<String> thingsIAmCurrentlyGetting = new HasSet<String>();
Object mutex = new Object();

BigThing getThing(String key) {
  synchronized(mutex) {
    while(thingsIAmCurrentlyGetting.contains(key)) {
      mutex.wait();
    }
    SoftReference<BigThing> ref = cache.get(key);
    BigThing bigThing = ref == null ? null : ref.get();
    if(bigThing != null) return bigThing;
    thingsIAmCurrentlyGetting.add(key);
  }

  BigThing bigThing = getBigThing(key); // this may take a while to run.

  synchronized(mutex) {
    cache.put(key, bigThing);
    thingsIAmCurrentlyGetting.remove(key);
    mutex.notifyAll();
  }

  return bigThing;
}

Я показываю свою старую школу здесь - новые пакеты java, вероятно, имеют намного более аккуратные способы сделать это.

Ответ 4

Не уверен, в чем вопрос здесь, но:

1) soft ref попытается сохранить ссылку, пока jvm действительно не потребует памяти. Отлично подходит для кешей, особенно LRU. Посмотрите на множество примеров в Гуаве.

2) слабый ref не пытается предотвратить gc, чтобы освободить объект вообще. Они используются, если вы хотите знать, используется ли этот объект где-то еще. Например, они используются для хранения информации о потоках и классах, поэтому, когда поток или класс больше не используются, мы можем отбросить метаинфо, связанный с этим.

3) phantom ref похожи на слабых, но не позволяют ссылаться на фактический объект. Таким образом, вы можете быть уверены, что передача phantom вокруг не может возобновить фактический объект (это риск со слабым ref). Кроме того, phantom ref блокирует объект, который будет собран, пока вы не очистите ref.

ReferenceQueue: вы не входите туда. gc сделает для вас. Они позволяют вам узнать, когда выпустят некоторые ссылки, не проверяя их по очереди.