1、饿汉模式
优点:在类初始化时已经实例化完成,调用时较快;线程安全
缺点:不管后期是否使用,都进行了一次初始化,有可能浪费资源
public class SingleTon{
private static final SingleTon mInstane=new SingleTon();
private SingleTon(){} //构造函数私有化
public static SingleTon getInstance(){
return mInstance;
}
}
2、懒汉模式(不推荐)
优点:只有在第一次使用时才会被初始化,一定程度上节约了资源
缺点:第一次加载时需要及时进行实例化,反应稍慢; 每次调用getInstance都进行同步,造成不必要的开销
public class SingleTon{
private SingleTon(){} //构造函数私有化
private static SingleTon mInstane=null;
public static synchronized SingleTon getInstance(){
if(mInstance == null){
mInstance=new SingleTon();
}
return mInstance;
}
}
3、DCL(Double CheckLock)
优点:第一次使用时才被初始化,节约资源; 线程安全; 第一次判null主要是为避免了不必要的同步
缺点:第一次加载时需要及时进行实例化,反应稍慢; 极低概率DCL失效,难以定位问题(jdk 1.5之后,mInstance添加volatile关键字可解决此问题)
PS: DCL失效问题可参考http://blog.itpub.net/28912557/viewspace-762047/
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;
}
}
4、静态内部类(推荐)
优点:第一次使用时才被初始化; 线程安全; 保证单例对象唯一性; 比优化过的DCL更“优雅”
缺点:第一次加载时需要及时进行实例化,反应稍慢
public class Singleton{
private Singleton(){} //构造函数私有化
public static Singleton getInstance(){
return SingletonHolder.mInstance;
}
private static class SingletonHolder{
private static final Singleton mInstance=new Singleton();
}
}
5、枚举单例(推荐)
优点:写法简洁; 枚举实例的创建是线程安全的; 并且在任何情况下它都是一个单例,其他几种方式在反序列化时会重新生成对象,要想防止反序列化,就要加入额外的代码( private Object readResolve() throws ObjectStreamException{return mInstance} )
public enum SingleTon{
INSTANCE;
public void doSomething(){
}
}
6、使用容器实现单例模式(有兴趣可以深入了解)
public class SingletonManager{
private static Map<String, Object> objMap=new HashMap<String, Object>();
private Singleton(){}
public static void registerService(String key , Object instance){
if(!objMap.containsKey(key)){
objMap.put(key, instance);
}
}
public static Object getService(String key){
return objMap.get(key);
}
}