使用 Java 的 ReferenceQueue

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14450538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 16:18:18  来源:igfitidea点击:

Using Java's ReferenceQueue

javamemorygarbage-collectionweak-referencessoft-references

提问by bgroenks

Do SoftReferenceand WeakReferencereally only help when created as instance variables? Is there any benefit to using them in method scope?

SoftReference并且WeakReference真的只在作为实例变量创建时有帮助吗?在方法范围内使用它们有什么好处吗?

The other big part is ReferenceQueue. Besides being able to track which references are determined garbage, can Reference.enqueue()be used to forcibly register an object for garbage collection?

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

For example, would it be worth to create a method that takes some heavy memory resources (held by strong references) in an object and creating References to enqueue them?

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

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

(Imagine that Object in this case represents an object type that uses a lot of memory... like BufferedImageor something)

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

Does this have any realistic effect? Or is this just a waste of code?

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

回答by Louis Wasserman

One common idiom with reference queues is to e.g. subclass WeakReferenceto attach information that's needed to clean up things, and then to poll a ReferenceQueueto get cleanup tasks.

引用队列的一种常见习惯用法是例如子类WeakReference以附加清理事物所需的信息,然后轮询 aReferenceQueue以获取清理任务。

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

For example, the internals of Guava's CacheBuilderimplementation when weakKeysare selected usesthis approach.

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

回答by Patashu

If an object has only WeakReferences (or no references whatsoever!) towards it, it can be garbage collected whenever Java needs to make more room in memory. So, you use WeakReferences whenever you want an object to remain in memory, but you don't need it to remain THAT badly (e.g. if Java needs to garbage collect it, no problem, you can get it back somehow and in the mean time Java has better performance)

如果一个对象只有WeakReferences(或没有任何引用!),那么只要 Java 需要在内存中腾出更多空间,它就会被垃圾回收。因此,WeakReference只要您希望对象保留在内存中,就可以使用s,但您不需要将它保留那么严重(例如,如果 Java 需要对其进行垃圾收集,没问题,您可以以某种方式将其取回,同时Java有更好的性能)

Enqueuing a WeakReferenceallows you to iterate the ReferenceQueueand determine which references have been garbage collected and which have not. That's all - so only do it if you need to know this.

入队 aWeakReference允许您迭代ReferenceQueue并确定哪些引用已被垃圾收集,哪些没有。这就是全部 - 所以只有在您需要知道这一点时才这样做。

Read more: http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

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

回答by PaulMurrayCbr

One common thing to do is to create maps of soft references.

一种常见的做法是创建软引用映射。

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;
}

I'm showing my old school here - the new java packages probably have much neater ways to do this.

我在这里展示我的旧学校 - 新的 java 包可能有更简洁的方法来做到这一点。

回答by Uberto

Not sure what is the question here but:

不确定这里的问题是什么,但是:

1) soft ref try to keep the reference until jvm really really needs the memory. Great for caches, esp LRU ones. Look at many examples in Guava.

1) soft ref 尝试保留引用,直到 jvm 真正需要内存。非常适合缓存,尤其是 LRU 缓存。查看 Guava 中的许多示例。

2) weak ref don't try to prevent gc to free the object at all. They are used if you want to know if that object is still used somewhere. For example they are used to store info about threads and classes, so that when the thread or the class is not used anymore we can discard the metainfo related to that.

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

3) phantom ref are like weak but without letting you reference the actual object. In this way you can be sure that passing the phantom around cannot resume the actual object (this is a risk with weak ref). Also phantom ref are blocking the object to be collected until you clear the ref.

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

ReferenceQueue: you don't enque stuff in there. gc will do for you. They allows you to know when some references get released, without having to check them one by one.

ReferenceQueue:你不要在那里排队。gc 会为你做的。它们使您可以知道某些参考文献何时发布,而无需一一检查。