您的位置:首页 > 编程语言 > Java开发

Java 单例模式

2013-11-05 16:46 68 查看
以前只知道Java中,单例模式有两种方法:

/*
* 	方法一:
* 	没有延迟加载,但却最简单
*/
public class Singleton {
private static final Singleton mInstance = new Singleton();

private Singleton(){}
public static Singleton getInstance(){
return mInstance;
}
}

方法一,也是《模式设计之禅》中写的,最简单省事的方法。

/*
* 	方法二:
* 	延迟加载
*/
public class Singleton {
private static Singleton mInstance = null;

private Singleton(){}
public synchronized static Singleton getInstance(){
if(mInstance == null){
mInstance = new Singleton();
}
return mInstance;
}
}

方法二,是为了延迟初始化mInstance而想出来的方法。

注:在方法上加了syncrhonized关键字。

那么,每次访问该方法,都会进入同步区,降低了访问性能,因为mInstance只在第一次为null,之后就已经有值了。不过,现在代的JVM性能已经很高了,所以,这里的性能损失也就可以忽略。

-------------------------------------------------------分割线------------------------------------------------------------

后来,在网上搜索了下JAVA单例还有没有其它方法,果然,另我汗颜,原来一共有5种,除去我上面讲的2种,下面讲其它3种:

/*
* 	方法三:
* 	静态内部类,加载时没有初始化mInstance,因此达到了延迟加载
*/
public class Singleton {
private static class InternalSingleton{
private static final Singleton mInstance = new Singleton();
}

private Singleton(){}
public static Singleton getInstance(){
return InternalSingleton.mInstance;
}
}

/*
* 	方法四:
* 	用枚举来实现单例模式
* 	《effective java》中作者推荐,也是能避免线程同步,
* 	同时还能避免Java中的反射(即反序列化)导致多个实例
*
* 	只有JDK1.5之后才支持枚举
*
* 	使用方法:Singleton.mInstance.function
*/
public enum Singleton{
mInstance;  // 默认mInstance = this

public void function(){
// ......
}
}

/*
* 	方法五:(在JAVA内存模型中,线程不安全,知道理论上可行就行了)
* 	双检索
* 	初衷:对比方法二,多个线程每次去getInstance时,
* 	都会进入synchronized状态,哪怕mInstance已经不
* 	为null,因此降低了性能,所以,将synchronized
* 	放在第一个if判断之后,再判断一次
*
* 	IBM大神有分析这种情况导致不安全的原因:
*  http://www.ibm.com/developerworks/cn/java/j-dcl.html */
public class Singleton {
private static Singleton mInstance = null;

private Singleton(){}
public static Singleton getInstance(){
if(mInstance == null){
synchronized(Singleton.class){
if(mInstance == null){
mInstance = new Singleton();
}
}
}
return mInstance;
}
}

本篇一共讲了5种方法,除了第5种“双检索”方法,知道就行了,但用的话,还是使用其它4种方法,不过,这里还是要说明点(网上也可以找到):

只有方法4,不但线程安全,同时也能JAVA反射机制,创造出N个单例的实例,不过我也说过,方法4使用的是枚举型,因为,至少要保证JDK1.5之上才行。

如果不讨论反射机制导致的问题,方法1,2,3和4都是可以用的。

因此,大家使用单例模式时,也请注意!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: