我将用一个声明来说明这个问题,即我是Java垃圾收集的新手,所以如果收集器处理这个问题,我会很高兴。或者,如果我是可悲的无知的Java内存分配,我实际上是,我很抱歉。但是,我正在考虑以下三种情形:Java - WeakReference最佳实践
public class ScenarioA implements MyQuestion{
private Field field;
public Field getField(){
if(field == null){
field = new Field(this);
}
return field;
}
与
public class ScenarioB implements MyQuestion{
public Field getField(){
return new Field(this);
}
}
与
import java.lang.ref.WeakReference;
public class ScenearioC implements MyQuestion{
private WeakReference<Field> weakField;
public Field getField(){
if(WeakField == null || weakField.get() == null){
weakField = new WeakReference(new Field(this));
}
return weakField.get();
}
}
我认为ScenarioA
只是坏,因为如果.get()
是不断呼吁我们将在ScenarioA
的实例和的实例之间保持强烈的引用由.get()
方法返回,这意味着既不会被垃圾收集,也不管程序实际上是否关心任何一个。
ScenarioB
存在潜在实例化大量.equal
对象的问题,这可能是非常昂贵和不必要的。
ScebarioC
我明白至少。我试图读取WeakReference
(here)的来源,但我无法弄清楚发生了什么。我想指责在幕后发生的某些GC/VM操作,但是我想把很多事情归咎于许多其他事情。无论如何,在我看来,每个WeakReference
都必须要求更多的内存,而不是简单地维护对象的引用,因为我们必须首先保留对WeakReference
的引用,然后引用实际对象。 (我对这句话表示歉意)。如果Field
很大并且/或者我们实例化了几个ScenarioA
's,这可能是不好的。更重要的是,在我看来,每个WeakReference
都需要自己的线程,除非实例ScenarioC
- 因此弱参考 - 死亡,否则它本身(线程)似乎永远不会死亡。如果有很多ScenarioC
的实例,这可能会非常糟糕。
有没有人有解决这个问题的办法?
场景A有问题,它不是线程安全的;如果线程安全是一个问题,不要这样做。 – fge
您的方案C可能会返回null,因为GC可能在收到weakField.get()之前收集弱引用对象。下面的答案有一个使用弱引用的更正确的版本。 – Gamlor