锁定老帖子 主题:对于单例模式的一点想法
精华帖 (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要确定等等,但是这种实现方法已经足够好了。 |
|
返回顶楼 | |
发表时间: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的标准行为。 |
|
返回顶楼 | |
发表时间: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(); 这种模式的话,对这个类的任何访问都会触发,比如这个类有什么全局常量的访问,也会触发初始化,但是此时根本不需要初始化。 |
|
返回顶楼 | |
发表时间:2008-07-06
Initialization on Demand Holder 好像是较早google的BOB提出的,也就是Guice的作者。其实Singleton说开了有很多可能导致意外多实例的情况。不同的VM,分布式应用比如EJB,RMI里面都可能出现假Singleton,不同的Class loader,比如applet在加载不同地址代码的时候可能发生意外,还有同步控制错误等。要防范所有的情况还真比较困难,个人看法最好还是让Singleton stateless,只负责对资源的存取,以策万全。
因为既便是很好防止了上面提到的种种可能,GC也可能制造一些麻烦(以为没人用就回收了,后来发现又有人要,只得重新创建一个Singleton,有状态也变没状态了) |
|
返回顶楼 | |
发表时间:2008-07-06
这贴为什么给新手帖这么多?
难道都理解了? ibm这篇http://www.ibm.com/developerworks/java/library/j-dcl.html out-of-order writes往后,就很难看下去了。 |
|
返回顶楼 | |
发表时间:2008-07-06
是不是考虑一下用ThreadLocal会更好呢,虽然不是单例模式
|
|
返回顶楼 | |
发表时间: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应该也是可行的. 不知道反对的人具体的什么原因呢? |
|
返回顶楼 | |
发表时间: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多半就是反模式,还不如不用,一般也就是放些不重要的,或者明显无状态的功能。 |
|
返回顶楼 | |
发表时间:2008-07-07
synchronized 的确实一种落后的声明了...
|
|
返回顶楼 | |
发表时间:2008-07-07
单例在分布式应用中应该特别注意!
|
|
返回顶楼 | |