自我释放(引用计数)单身

时间:2013-12-19 08:28:37

标签: java memory-management garbage-collection singleton

请考虑以下情形: 您有一个代表某种数据提供者的单例类。 这个单例类分配了大量的内存,你希望它在没有人使用时释放它的已分配内存。 流速:

  1. Class A调用getInstance并使用singleton(这是第一次调用getInstance,singleton类分配大量内存块)
  2. B类调用getInstance并使用singleton
  3. A级和B级“死”(现在没有人使用单身)
  4. 程序仍在运行,但单例的内存未释放。
  5. 你如何建议在第3阶段实现单例(A类和B类“死”)将释放内存(我知道java使用垃圾收集,但仍然可以说我想要以下内存= null)。

    PS 我不想强迫每个类在单例停止使用它时使用单例调用释放。我希望单身人士自己处理“释放”记忆。

2 个答案:

答案 0 :(得分:7)

你能做的是

  • 仅在第一次要求时创建单身人士。
  • 将其存储在WeakReference中。如果GC在其他地方仍然具有“强大”参考,那么这只会在GC之后保持活跃状态​​。

如果WeakReference.get()null,这意味着它已被收集,因为没有人强烈使用它,另一个弱引用不计算在内。如果再次需要它,您需要重新创建它和WeakReference

像这样,

public enum SingletonHolder{; // no instances

    private static WeakReference<MyType> ref = null;

    public static synchronized MyType getInstance() {
         MyType type = ref == null ? null : ref.get();
         if (type == null)
             ref = new WeakReference<MyType>(type = new MyType());
         return type;
    }
}

BTW这假设需要此实例的实例保留对它的引用。这就是弱参考“知道”它仍然需要它的方式。

BTW2如果它是单线程的,你不需要同步,但它应该是无害的。

这意味着只有当新实例第一次需要它时才应该调用此方法,而不是每次都要调用此方法并使其更高性能不会产生太大影响,例如:双重检查只会让它变得复杂。

答案 1 :(得分:1)

使用Design pattern: "Singleton"非常常见,常见的实施方法是使用static reference

此实现的问题在于它多次离开floating garbage未使用。

例如: 一个singleton,其中包含DB connection pool,只有应用程序在启动时才需要加载。

因此,更好的解决方案是对Singleton设计模式的扩展,称为WeakSingleton

当原始实例的所有其他引用都已过期时,此模式执行预期的操作,清除实例。

在java中实现此模式非常简单,可以基于WeakReferences

<强> E.g。代码:

public class WeakSingleton{

static private WeakReference singleton; // instance

public WeakSingleton getInstance(){

  WeakSingleton m = (WeakSingleton)singleton.get();

  if( m != null)

     return m;

  synchronized (WeakSingleton.class){

     m = (WeakSingleton)singleton.get();

     if( m != null)

    return m;       

    m = new WeakSingleton(); // creates new instnace 

    singleton = new WeakReference(m);

  } 

  return m;

 }

}