使用Java的ReferenceQueue

bgr*_*nks 23 java memory garbage-collection weak-references soft-references

不要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();
}
Run Code Online (Sandbox Code Playgroud)

(想象一下,在这种情况下,Object表示一个使用大量内存的对象类型...喜欢BufferedImage什么的)

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

Lou*_*man 32

参考队列的一个常见习惯是例如子类WeakReference附加清理事物所需的信息,然后轮询a 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().
}
Run Code Online (Sandbox Code Playgroud)

例如,选择Guava CacheBuilder实现的内部时使用这种方法.weakKeys


Pat*_*shu 5

如果一个对象只有WeakReferences(或者没有任何引用!),那么每当Java需要在内存中腾出更多空间时,它就可以被垃圾收集.所以,WeakReference只要你想让一个对象保留在内存中就可以使用s,但是你不需要它来保持那么糟糕(例如,如果Java需要垃圾收集它,没问题,你可以在某种程度上同时恢复它Java有更好的性能)

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

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

  • @Patashu,如果我可以做到 if (weekReference.get() == null) ,为什么我需要一个 ReferenceQueue 来“确定哪些引用已被 GC-d”? (2认同)
  • @Gavriel 因为像“while (weakReference.get() != null)”这样的忙循环会消耗太多 CPU。`ReferenceQueue` 让你休眠,直到有一个对象可供你完成。 (2认同)

Pau*_*Cbr 5

要做的一件事是创建软引用的映射。

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;
}
Run Code Online (Sandbox Code Playgroud)

我在这里显示我的老派-新的Java程序包可能有很多更整齐的方法来做到这一点。