前言
记录单例模式的多种使用方式,以及自己的理解
饿汉模式
public class HungrySingleMode {
private static HungrySingleMode mInstance=new HungrySingleMode();
private HungrySingleMode(){}
public static HungrySingleMode getInstance(){
return mInstance;
}
}
个人理解
类加载的时候把静态的变量已经加载到内存里了,使用的时候直接获取不用再创建实例对象,运行时稍微快一些。如果没有被使用,则有点浪费内存。因为在类加载的时候已经创建了唯一的实例,所以在多线程运行的时候不会出现同步的问题。
懒汉模式(线程不安全)
public class LazySingleMode {
private static LazySingleMode mInstance=null;
private LazySingleMode(){}
public static LazySingleMode getInstance(){
if(mInstance==null){
mInstance=new LazySingleMode();
}
return mInstance;
}
}
个人理解
在第一次调用的时候才会创建实例,这就导致运行的时候会稍微慢一些,但是又保证了不会浪费内存。在同步方面如果两个线程同时调用这个方法,由于没有同步锁的控制,会导致创建多个实例,会出现同步问题。
懒汉模式(线程安全)
public class LazySingleSafeMode {
private static LazySingleSafeMode mInstance;
private LazySingleSafeMode(){}
public static synchronized LazySingleSafeMode getInstance(){
if(mInstance==null){
mInstance=new LazySingleSafeMode();
}
return mInstance;
}
}
个人理解
在调用的方法上加上同步锁解决同步问题,但是每次调用都要去判断同步的问题,增加了开销。
双重检查模式(DCL)
public class DLCSingleMode {
private volatile static DLCSingleMode mInstance;
private DLCSingleMode(){}
public static DLCSingleMode getInstance(){
if (mInstance==null){
synchronized (DLCSingleMode.class){
if(mInstance==null){
mInstance=new DLCSingleMode();
}
}
}
return mInstance;
}
}
个人理解
首先,静态变量用volatitle关键字申明,保证了原子性(有待深入理解)。
其次,在调用方法里面进行了两次判空,第二次判空进行代码块的同步锁定,保证同步问题。第一次判空可以避免多次同步的调用,既保证同步也避免了多余的同步开销浪费。
最后,在某些情况下也会存在失效的问题,具体情况待深入理解。
静态内部类
public class StaticInnerSingleMode {
private StaticInnerSingleMode(){}
public static StaticInnerSingleMode getInstance(){
return SingletonHolder.instance;
}
private static class SingletonHolder{
private static final StaticInnerSingleMode instance=new StaticInnerSingleMode();
}
}
个人理解
在类加载的时候,不会初始化instance实例,只有在第一次调用的时候才会创建实例,同时也能保证线程安全。
枚举单例
public enum EnumSingleMode {
INSTANCE;
public void doSomeThing(){}
}
个人理解
默认枚举实例的创建时线程安全的,并且在任何情况下都是单列。–《Android 进阶之光》 刘望舒
总结
经过看书学习使用对单例模式有更深刻的认识,当然还有一些不理解之处,需要继续研究。