1.饿汉模式
在使用该类的时候就会在内存中初始化一个单例对象,当我们调用getInstance()的时候直接获取该对象。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
2.懒汉模式
在我们调用getInstance()静态方法后才去创建该对象,为了解决同步问题,在getInstance()方法上加锁,每次只允许一个线程进来,虽然同步问题解决了,但是性能不佳。
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 volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
INSTANCE = new SingleTon();
这个步骤,其实在jvm里面的执行分为三步:
1.在堆内存开辟内存空间。
2.在堆内存中实例化SingleTon里面的各个参数。
3.把对象指向堆内存空间。
由于jvm存在乱序执行功能,所以可能在2还没执行时就先执行了3,如果此时再被切换到线程B上,由于执行了3,INSTANCE 已经非空了,会被直接拿出来用,这样的话,就会出现异常。这个就是著名的DCL失效问题。
4.静态内部类
外部类加载时不需要立即加载内部类。这样延迟了单例的实例化
public class Singleton {
private Singleton(){
}
public static Singleton getInstance(){
return Inner.instance;
}
private static class Inner {
private static final Singleton instance = new Singleton();
}
}
5.枚举单例
public enum Singleton {
INSTANCE
//doSomething 该实例支持的行为
//可以省略此方法,通过Singleton.INSTANCE进行操作
public static Singleton get Instance() {
return Singleton.INSTANCE;
}
}