论坛首页 Java企业应用论坛

对于单例模式的一点想法

浏览 23649 次
精华帖 (1) :: 良好帖 (9) :: 新手帖 (11) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-07-05  
以前有人讨论过。
一种比较好的实现方式是Initialization on Demand Holder (IODH):

public   class  Singleton  {   
   static  class  SingletonHolder  { 
     static  Singleton instance  =   new  Singleton();   
   }
  
   public   static  Singleton getInstance()  {   
     return  SingletonHolder.instance;   
  }    
}


能够达到Lazy Singleton的效果,即只有需要的时候,才初始化,而且只需要初始化一次。
这是依靠JVM对内部静态类&静态成员初始化的顺序机制来实现的。
这种实现方法虽然有一定的局限性,比如,只能用于静态成员,ClassLoader要确定等等,但是这种实现方法已经足够好了。
0 请登录后投票
   发表时间:2008-07-06  
buaawhl 写道
以前有人讨论过。
一种比较好的实现方式是Initialization on Demand Holder (IODH):

public   class  Singleton  {   
   static  class  SingletonHolder  { 
     static  Singleton instance  =   new  Singleton();   
   }
  
   public   static  Singleton getInstance()  {   
     return  SingletonHolder.instance;   
  }    
}


能够达到Lazy Singleton的效果,即只有需要的时候,才初始化,而且只需要初始化一次。
这是依靠JVM对内部静态类&静态成员初始化的顺序机制来实现的。
这种实现方法虽然有一定的局限性,比如,只能用于静态成员,ClassLoader要确定等等,但是这种实现方法已经足够好了。

我觉得这种方法跟我提到的第一种方法没有什么区别,就是
public static final Singleton INSTANCE=new Singleton();

你是不是说这种方法不是lazy init的?但我试验的结果就是laze的。
即static变量不是在class加载的时候初始化的,而是在实例化此类第一个实例的时候初始化的。
不知道这是不是JVM的标准行为。
0 请登录后投票
   发表时间:2008-07-06  
Lucas Lee 写道
buaawhl 写道
以前有人讨论过。
一种比较好的实现方式是Initialization on Demand Holder (IODH):

public   class  Singleton  {   
   static  class  SingletonHolder  { 
     static  Singleton instance  =   new  Singleton();   
   }
  
   public   static  Singleton getInstance()  {   
     return  SingletonHolder.instance;   
  }    
}


能够达到Lazy Singleton的效果,即只有需要的时候,才初始化,而且只需要初始化一次。
这是依靠JVM对内部静态类&静态成员初始化的顺序机制来实现的。
这种实现方法虽然有一定的局限性,比如,只能用于静态成员,ClassLoader要确定等等,但是这种实现方法已经足够好了。

我觉得这种方法跟我提到的第一种方法没有什么区别,就是
public static final Singleton INSTANCE=new Singleton();

你是不是说这种方法不是lazy init的?但我试验的结果就是laze的。
即static变量不是在class加载的时候初始化的,而是在实例化此类第一个实例的时候初始化的。
不知道这是不是JVM的标准行为。


lazy只是个说法,lazy的程度是不一样的。

举例如下:
IODH模式下,只有在调用getInstance()的时候才会发生初始化。
但是
public static final Singleton INSTANCE=new Singleton();

这种模式的话,对这个类的任何访问都会触发,比如这个类有什么全局常量的访问,也会触发初始化,但是此时根本不需要初始化。
1 请登录后投票
   发表时间:2008-07-06  
Initialization on Demand Holder 好像是较早google的BOB提出的,也就是Guice的作者。其实Singleton说开了有很多可能导致意外多实例的情况。不同的VM,分布式应用比如EJB,RMI里面都可能出现假Singleton,不同的Class loader,比如applet在加载不同地址代码的时候可能发生意外,还有同步控制错误等。要防范所有的情况还真比较困难,个人看法最好还是让Singleton stateless,只负责对资源的存取,以策万全。
因为既便是很好防止了上面提到的种种可能,GC也可能制造一些麻烦(以为没人用就回收了,后来发现又有人要,只得重新创建一个Singleton,有状态也变没状态了)
0 请登录后投票
   发表时间:2008-07-06  
这贴为什么给新手帖这么多?
难道都理解了?
ibm这篇http://www.ibm.com/developerworks/java/library/j-dcl.html
out-of-order writes往后,就很难看下去了。
0 请登录后投票
   发表时间:2008-07-06  
是不是考虑一下用ThreadLocal会更好呢,虽然不是单例模式
0 请登录后投票
   发表时间:2008-07-06  
buaawhl 写道
以前有人讨论过。
一种比较好的实现方式是Initialization on Demand Holder (IODH):

public   class  Singleton  {   
   static  class  SingletonHolder  { 
     static  Singleton instance  =   new  Singleton();   
   }
  
   public   static  Singleton getInstance()  {   
     return  SingletonHolder.instance;   
  }    
}


能够达到Lazy Singleton的效果,即只有需要的时候,才初始化,而且只需要初始化一次。
这是依靠JVM对内部静态类&静态成员初始化的顺序机制来实现的。
这种实现方法虽然有一定的局限性,比如,只能用于静态成员,ClassLoader要确定等等,但是这种实现方法已经足够好了。


c#的msdn上面是这种方法.java上面的机制应该也是可以的.虽然static属性是第一次使用类的时候初始化,但是这种子class的应该是第一次使用这个子的class的时候才进行初始化的吧.

还有那个使用0,1来进行二次检测的方法.我觉得应该是可行的.使用元数据类型的话不存在创建时间之类的问题.true,false应该也是可行的.

不知道反对的人具体的什么原因呢?

10 请登录后投票
   发表时间:2008-07-06  
Mozart 写道
Initialization on Demand Holder 好像是较早google的BOB提出的,也就是Guice的作者。其实Singleton说开了有很多可能导致意外多实例的情况。不同的VM,分布式应用比如EJB,RMI里面都可能出现假Singleton,不同的Class loader,比如applet在加载不同地址代码的时候可能发生意外,还有同步控制错误等。要防范所有的情况还真比较困难,个人看法最好还是让Singleton stateless,只负责对资源的存取,以策万全。
因为既便是很好防止了上面提到的种种可能,GC也可能制造一些麻烦(以为没人用就回收了,后来发现又有人要,只得重新创建一个Singleton,有状态也变没状态了)



Singleton的应用比较狭窄,如果出现如上场景,Singleton多半就是反模式,还不如不用,一般也就是放些不重要的,或者明显无状态的功能。
0 请登录后投票
   发表时间:2008-07-07  
synchronized  的确实一种落后的声明了...
0 请登录后投票
   发表时间:2008-07-07  
单例在分布式应用中应该特别注意!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics