使用Java的的ReferenceQueue(Using Java's ReferenceQ

2019-07-18 12:26发布

不要SoftReferenceWeakReference时候为实例变量创建真的只有帮助吗? 有没有在方法范围使用它们的好处?

另外很大一部分是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();
}

(试想一下,对象在这种情况下,表示使用了大量的内存...喜欢的对象类型BufferedImage或东西)

这是否有任何真实的效果? 或者这只是一个代码浪费?

Answer 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().
}

例如,番石榴的的内部CacheBuilder实现时weakKeys选择使用这种方法。



Answer 2:

如果一个对象有唯一WeakReference S(或根本没有任何参考!)对,它可以被垃圾收集每当Java需要腾出存储器空间。 因此,您使用WeakReference小号,只要你想要的目的是保留在内存中,但你并不需要它仍然认为严重(例如,如果Java需要垃圾回收它,没问题,你可以找回来不知何故,并在平均时间Java有更好的性能)

一个入队WeakReference让你迭代ReferenceQueue并确定哪些引用都被垃圾回收,哪些还没有。 这一切 - 因此,只有当你需要知道这一点做到这一点。

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



Answer 3:

做一个普通的事情就是创建软引用的地图。

Map<String, SoftReference<BigThing>> cache = new HashMap<>();
Set<String> thingsIAmCurrentlyGetting = new HashSet<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包可能有非常巧妙的方式来做到这一点。



Answer 4:

不知道是什么问题,但在这里:

1)软裁判尽量保持基准直到JVM真的需要的内存。 伟大的缓存,尤其LRU的。 看看番石榴例子很多。

2)弱裁判不要试图阻止GC来释放对象都没有。 如果你想知道,如果该对象仍然是使用它们的地方使用。 例如,它们用于存储有关线程和类信息,这样,当线程或类不再使用,我们可以放弃相关的元信息。

3)幻影裁判都像弱,但没有让您引用实际的对象。 通过这种方式,你可以肯定的是周围路过的幻象不能恢复实际的对象(这是弱REF风险)。 此外幻象裁判被封锁要收集的对象,直到您清空裁判。

的ReferenceQueue:你不要在那里enque东西。 GC会为你做。 他们可以让你知道,当一些参考得到释放,而不必逐个检查这些之一。



文章来源: Using Java's ReferenceQueue