使用Java的ReferenceQueue

SoftReferenceWeakReference真的只在创建为实例变量时才有用吗? 在方法范围内使用它们有什么好处吗?

另一个重要的部分是ReferenceQueue 。 除了能够跟踪哪些引用被确定为垃圾之外,还可以使用Reference.enqueue()来强制注册垃圾回收对象吗?

例如,是否值得创建一个方法,该方法在对象中占用大量内存资源(由强引用保存)并创建引用以将它们排入队列?

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

(想象一下,在这种情况下,Object表示一个使用大量内存的对象类型……比如BufferedImage或者其他东西)

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

参考队列的一个常见习惯是例如将WeakReference子类WeakReference附加清理事物所需的信息,然后轮询ReferenceQueue以获得清理任务。

 ReferenceQueue fooQueue = new ReferenceQueue(); class ReferenceWithCleanup extends WeakReference { 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时,Guava的CacheBuilder实现的内部使用这种方法。

如果一个对象只有WeakReference (或者没有任何引用!),那么每当Java需要在内存中腾出更多空间时,它就可以被垃圾收集。 因此,只要您希望对象保留在内存中,就可以使用WeakReference ,但是您不需要它保持严重(例如,如果Java需要垃圾收集它,没问题,您可以以某种方式将其恢复到平均值时间Java有更好的表现)

排队WeakReference允许您迭代ReferenceQueue并确定哪些引用已被垃圾收集,哪些没有。 这就是全部 – 所以只有你需要知道这一点。

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

一个常见的事情是创建软引用的映射。

 Map> cache = new HashMap<>(); Set thingsIAmCurrentlyGetting = new HashSet(); Object mutex = new Object(); BigThing getThing(String key) { synchronized(mutex) { while(thingsIAmCurrentlyGetting.contains(key)) { mutex.wait(); } SoftReference 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软件包可能有更简洁的方法来做到这一点。

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

1)soft ref尝试保持引用,直到jvm确实需要内存。 非常适合缓存,尤其是LRU。 看看番石榴中的许多例子。

2)弱参考不要试图阻止gc释放对象。 如果您想知道该对象是否仍在某处使用,则使用它们。 例如,它们用于存储有关线程和类的信息,因此当不再使用线程或类时,我们可以丢弃与之相关的元信息。

3)幻像参考就像弱,但没有让你参考实际的对象。 通过这种方式,您可以确保传递幻像无法恢复实际对象(这是一个弱参考的风险)。 幻象参考也会阻止要收集的对象,直到您清除参考。

ReferenceQueue:你不会在那里使用东西。 gc会为你做的。 它们允许您知道某些引用何时被释放,而无需逐个检查它们。