DCL(双重检查加锁)
public class Singleton
{
//volatile确保对singleton的读写操作不会同时进行,不会出现读取到错误值的情况
//如果不用volatile进行修饰,可能会出现在getInstance()时读取到错误值的情况,因为new不是原子操作,包含了好几步操作,这几步操作很可能是这样:使singleton对象与引用相关联发生在初始化singleton之前,这种操作在单线程下看对后面是不会有影响的,但是多线程会造成另一个线程调用getInstance()时发现singleton不是null,但其实还没有初始化完毕导致读到错误的值
private volatile Singleton singleton = null;
//建议所有的单例模式构造器都是私有的,防止在类外部建立多个实例
private Singleton() {}
public static Singleton getInstance() {
//第一次检查是否已经生成了实例
if (singleton== null) {
synchronized (Singleton.class) {
//如果有多个线程获得了这个锁,第二次检查确保第二个线程进来不会再次生成新的实例
if (singleton== null) {
singleton= new Singleton();
}
}
}
return singleton;
}
}
提前初始化模式
public class Singleton
{
//在类被加载的时候就会生成singleton实例,所以不会有线程安全问题
private static Singleton singleton = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return singleton;
}
}
延长初始化占位类模式
public class Singleton {
//加载Singleton类的时候不会加载SingletonHolder类,只有第一次访问SingletonHolder类时才会加载
private static class SingletonHolder {
private static Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚举实现单例模式
public enum Singleton{
INSTANCE;
public void test() {
System.out.println("你调用了test()!");
}
}
枚举类默认构造方法就是私有的,并且只能是私有的.