1. 饿汉式
// 饿汉式public class Singleton { private static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return INSTANCE; }}
2. 懒汉式
public class Singleton { private static Singleton INSTANCE; private Singleton() {} public static Singleton getInstance() { if (INSTANCE == null) { INSTANCE = new Singleton(); } return INSTANCE; }}
3. 线程平安懒汉式-双重查看
public class Singleton { private static Singleton INSTANCE; private Singleton() {} public static Singleton getInstance() { if (INSTANCE == null) { synchronized(Singleton.class) { if (INSTANCE == null) { INSTANCE = new Singleton(); } } } return INSTANCE; }}
4. 双重查看的不足之处
以下三种状况会毁坏双重查看的单例模式:指令重排序、序列/反序列化、反射
4.1 指令重排序
INSTANCE = new Singleton()
语句并非原子操作,分为以下三步:
- 调配Singleton对象内存空间。
- 初始化对象。
- 将INSTANCE对象援用指向调配的内存空间。
因为指令重排序的问题,以上指令在理论状况可能以1 -> 3 -> 2的程序执行。
在多线程的状况下可能呈现:
执行程序 | 线程 A | 线程 B |
---|---|---|
1 | 调配Singleton对象内存空间 | |
2 | 将INSTANCE对象援用指向调配的内存空间 | |
3 | 拜访getInstance()办法,判断INSTANCE对象是否为null | |
4 | 因为INSTANCE曾经实现了对象援用指向,因为不为null,但此时INSTANCE还没有实现初始化 | |
5 | 初始化对象 | |
6 | 拜访INSTANCE援用的对象 |
解决办法:
应用volatile润饰INSTANCE对象
public class Singleton { private volatile static Singleton INSTANCE; private Singleton() {} public static Singleton getInstance() { if (INSTANCE == null) { synchronized(Singleton.class) { if (INSTANCE == null) { INSTANCE = new Singleton(); } } } return INSTANCE; }}
4.2 序列/反序列化毁坏单例
参考大佬文章:https://segmentfault.com/a/11...
如果想要避免单例被序列/反序列化毁坏。就让单例类实现readResolve()办法。
public class Singleton { private volatile static Singleton INSTANCE; private Singleton() {} public static Singleton getInstance() { if (INSTANCE == null) { synchronized(Singleton.class) { if (INSTANCE == null) { INSTANCE = new Singleton(); } } } return INSTANCE; } private Object readResolve() { return Singleton.INSTANCE; }}
4.3 反射毁坏单例
参考大佬文章:https://segmentfault.com/a/11...
为了避免反射毁坏单例,采纳枚举实现单例模式。
public enum EnumSingleton { INSTANCE; public EnumSingleton getInstance(){ return INSTANCE; }}
参考文献
https://www.liaoxuefeng.com/w...
https://segmentfault.com/a/11...