Java基础—单例模式
1. 懒汉式,线程不安全
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
2. 懒汉式, 线程安全
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
3. 饿汉式
public class Singleton {
private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
4. 双重校验,double-checked locking
public class Singleton {
private static volatile Singleton INSTANCE;
private Singleton() { }
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
INSTANCE = new Singleton();
}
}
return INSTANCE;
}
}
5. 静态内部类
public class Singleton {
private static class SingletonHolder {
private final static Singleton INSTANCE = new Singleton ();
}
private Singleton() { }
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
6. 枚举
public enum Singleton {
INSTANCE
}
不推荐使用第1种和第2种
懒汉式
,可以使用第3种饿汉式
,需要懒加载可以使用第4种双重校验
和第5种静态内部类
,如果涉及到反序列化创建对象需要用第6种枚举
去实现。双重校验的
volatile
关键字不可缺失,保证初始化三步骤不会被指令优化重排。三步骤是:1)分配空间 2)初始化值 3)将对象指向刚分配的空间。正常为1-2-3,重排变成1-3-2静态内部类利用classloader机制,在静态内部类没有访问的时候,
INSTANCE
是不会被初始化的,而静态内部类只会被加载一次。枚举为最佳单例实现方式。简洁,反序列化后仍然是同一实例,
Constructor
类的newInstance
方法有判定对enum的类反射会抛出异常。(enum本质上是一个抽象类,新建一个枚举类就是继承了enum这个抽象类,只能用enum的构造方案)
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");