- 饿汉式
- 懒汉式/Double check(双重检索)
- 静态内部类
- 枚举单例
饿汉式
private static final DispatchSingleton instence = new DispatchSingleton();public static DispatchSingleton getInstence() {return instence;}
饿汉式是在jvm加载这个单例类的时候,就会初始化这个类中的实例,在使用单例中的实例时直接拿来使用就好,因为加载这个类的时候就已经完成初始化,并且由于是已经加载好的单例实例因此是线程安全的,并发获取的情况下不会有问题,是一种可投入使用的可靠单例。
优点:使用起来效率高、线程安全
缺点:由于jvm在加载单例类的时候需要初始化单例实例,因此在加载单例的时候针对jvm内存不够友好。
懒汉式
private static DispatchSingleton mSluggardInstence;public static DispatchSingleton getSluggardInstence(){if (mSluggardInstence==null){mSluggardInstence=new DispatchSingleton();}return mSluggardInstence;}
最简单的懒汉式,核心思想就是弥补饿汉式的缺点,在jvm加载单例类的时候不去初始化实例,而是在第一次获取实例的时候再去初始化实例。但是这样理论完美的单例在使用的时候有一个致命的缺点,在多线程使用的情况下,有时会出现不同线程从单例实例中获取不同的实体。针对多线程环境中并不可靠。
优点:针对jvm内存比较友好,实现了实例的懒加载。
缺点:多线程环境下不安全,会出现不同线程从单例实例中获取不同的实体的情况。
private static volatile DispatchSingleton mSluggardInstence;public static DispatchSingleton getSluggardInstence() {if (mSluggardInstence == null) {synchronized (DispatchSingleton.class) {if (mSluggardInstence == null) {mSluggardInstence = new DispatchSingleton();}}}return mSluggardInstence;}
synchronized
针对懒汉式的这种线程不安全的现:在单例初始化时,多线程存在创建多次实例的风险
“锁的粒度",锁的粒度: 粗和细加锁代码涉及到的范围,加锁代码的范围越大,认为锁的粒度越粗范围越小,则认为粒度越细
所以synchronized锁住获取实例的整个方法也可以解决问题,且在并发获取单例实例的时候会有性能问题。故此减小锁的粒度。
volatile
在于jdk1.5开始针对volatile进行了增强,因为Volatile会禁止指令重排序
静态内部类
private static class Holder{private static DispatchSingleton singleton = new DispatchSingleton();}public static DispatchSingleton getHolderInstence() {return Holder.singleton;}
静态内部类的优点是:外部类加载时并不会立即加载内部类,内部类不被加载就不去初始化实例,因此实现了懒加载。当DispatchSingleton第一次被加载时,并不需要去加载内部类Holder,只有当getInstance()方法第一次被调用时,才会导致虚拟机加载Holer类菜会去初始化StaticSingle实例。这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。
枚举单例
以上解决了效率或者懒加载以及线程安全的问题,但是它们都有两个共同的缺点: 序列化可能会破坏单例模式
public enum DispatchSingle {INSTANCE;public void doSomething(){}}
- 自由序列化
- 保证只有一个实例
- 线程安全
- 与静态内部类的区别
- 枚举单例为直接加载,静态内部类为懒加载
- 两者相比较,静态内部类比较节省资源开销
我们也可以像常规类一样编写enum类,为其添加变量和方法,访问方式也更简单,使用DispatchSingle .INSTANCE进行访问,这样也就避免调用getInstance方法,更重要的是使用枚举单例的写法,我们完全不用考虑序列化和反射的问题。枚举序列化是由jvm保证的,每一个枚举类型和定义的枚举变量在JVM中都是唯一的。