本文章参考订阅号程序员小灰(漫画风格)
单例模式:一个类只能构建一个对象的设计模式。
非线程安全单例模式:
---------懒汉式----------
public class Singleton { private Singleton() {} //私有构造函数 private static Singleton instance = null; //单例对象 //静态工厂方法 public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }---------饿汉式----------
public class Singleton { private Singleton() {} //私有构造函数 private static Singleton instance = new Singleton(); //类加载的时候初始化 //静态工厂方法 public static Singleton getInstance() { return instance; } }
构成单例模式关键点:
- 一个类只能构建一个对象,必须有私有的构造函数
- 还有单例对象,这有2种写法,一种是null,这类需要判断是否为null才可以去进行创建,叫懒汉模式;另一种是new Singleton()主动构建,属于饿汉模式
- getInstance是获取单例对象的方法
线程安全:
在 if (instance == null) { instance = new Singleton(); }这个条件中,如果同时又A,B俩个线程同时进入,因为Instance是空,所以两个线程同时通过了条件判断, 开始执行new操作:这样一来,显然instance被构建了两次。public class Singleton { private Singleton() {} //私有构造函数 private volatile static Singleton instance = null; //单例对象 //静态工厂方法 public static Singleton getInstance() { if (instance == null) { //双重检测机制 synchronized (Singleton.class){ //同步锁 if (instance == null) { //双重检测机制 instance = new Singleton(); } } } return instance; } }
- 为了防止new Singleton被执行多次,因此在new操作之前加上Synchronized 同步锁
- 进入Synchronized 临界区以后,还要再做一次判空。因为当两个线程同时访问的时候,线程A构建完对象,线程B也已经通过了最初的判空验证,不做第二次判空的话,线程B还是会再次构建instance对象。
- volatile阻止了变量访问后的指令重排,保证了执行指令顺序。