1.饿汉模式
顾名思义就是非常急迫,实例在类加载的时候就创建了,创建实际非常早,相当于程序一启动,实例就创建了.
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){};
public Singleton getInstance(){
return instance;
}
}
2.懒汉模式
顾名思义就是非常懒,等需要时才创建.
单线程版
class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
多线程版
public class SingletonLazy {
private static Object locker = new Object();
private volatile static SingletonLazy instance = null;
private SingletonLazy() {}
public SingletonLazy getInstance() {
if (instance == null) {
synchronized (locker) {
if (instance == null) {
instance = new SingletonLazy();
}
}
}
return instance;
}
}
我们来看单线程版到多线程版之间的演变
第一步我们先看单线程代码为什么到多线程中为什么是不安全的
如上图所示,如果t1线程判断完instance == null被调度出cpu之后,t2在执行并且new出实例之后,在执行t1那么t1就又会new出一个新实例,前后得到两个实例不一样,这就不是单例模式了.
那么我们这里的解决方案就是给这里加一个锁就变成下面这样
class Singleton {
private static Object locker = new Object();
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
synchronized (locker) {
if (instance == null) {
instance = new Singleton();
}
}
return instance;
}
}
这里我们可以在synchronized外面再加一个if判断语句,这让可以让第一次创建出实例之后在调用这个方法不用每次都进锁判断那么就变成了下面这样
class Singleton {
private static Object locker = new Object();
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (locker) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
第二部就是我们的指令重排序了,这里的instance = new Singleton();这是三个指令完成的.由于我们在前面的博客介绍了,这里就简单介绍一下
三个指令
1.申请一段内存空间
2.在这个内存上调用构造方法,创建出这个实例
3.把这个内存地址赋值给instance引用变量
由于编译器优化可能会优化成1,3,2
这个问题加上volatile就能解决,volatile能阻止编译器指令重排序.
那么最后就变成了我们看到的最终代码了
public class SingletonLazy {
private static Object locker = new Object();
private volatile static SingletonLazy instance = null;
private SingletonLazy() {}
public SingletonLazy getInstance() {
if (instance == null) {
synchronized (locker) {
if (instance == null) {
instance = new SingletonLazy();
}
}
}
return instance;
}
}