第一种:非延迟加载单例类
public class Singleton {
private Singleton() {}
private static final Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
第二种:同步延迟加载
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
第三种:双重检测同步延迟加载
为处理原版非延迟加载方式瓶颈问题,我们需要对 instance 进行第二次检查,目的是避开过多的同步(因为这里的同步只需在第一次创建实例时才同步,一旦创建成功,以后获取实例时就不需要同获取锁了),instance为volatile则可行:
public class Singleton {
private volatile static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {// 1
if (instance == null) {// 2
instance = new Singleton();// 3
}
}
}
return instance;
}
}
这里是主要是要理解为什么要使用volatile修饰变量才行,是因为:
volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作,所以才不会出现对象还在创建就被其他线程拿去使用的情况,其他线程都会得到一个创建好的对象
第四种:使用内部类实现延迟加载
public class Singleton {
private Singleton() {}
private static class Holder {
private static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
// 外围类能直接访问内部类(不管是否是静态的)的私有变量
return Holder.instance;
}
}