使用 Java 的 ReferenceQueue

是否并且真的仅在创建为实例变量时才有帮助?在方法范围内使用它们有什么好处吗?SoftReferenceWeakReference

另一个重要部分是.除了能够跟踪哪些引用是确定的垃圾之外,还可用于强制注册垃圾回收对象?ReferenceQueueReference.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

这有什么现实效果吗?或者这只是浪费代码?


答案 1

引用队列的一个常见习语是例如子类附加清理内容所需的信息,然后轮询a以获取清理任务。WeakReferenceReferenceQueue

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在选择时实现的内部使用这种方法。CacheBuilderweakKeys


答案 2

如果一个对象只有s(或没有任何引用!),那么每当Java需要在内存中腾出更多空间时,它就可以被垃圾回收。所以,每当你想让一个对象保留在内存中时,你都会使用s,但你不需要它保持那么糟糕(例如,如果Java需要垃圾回收它,没问题,你可以以某种方式把它拿回来,同时Java有更好的性能)WeakReferenceWeakReference

通过对 a 进行排队,您可以迭代并确定哪些引用已被垃圾回收,哪些引用尚未被垃圾回收。仅此而已 - 所以只有在您需要知道这一点时才这样做。WeakReferenceReferenceQueue

阅读更多: http://weblogs.java.net/blog/2006/05/04/understanding-weak-references