单例模式
保证单例对象的类只有一个实例
优点:不会频繁地创建和销毁对象,浪费系统资源
- 饿汉式:提前创建好 static 对象
// 饿汉式单例
class Hungry {
// 私有化构造器,不能new
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance() {
return HUNGRY;
}
}
- 双检索懒汉式
/**
* 指令重排避免
* 双重检测锁 + 原子性操作
* 无视私有的构造器
* 反射可以破环单例
* 反射不能破环枚举的单例
* 枚举中没有无参构造
*/
class LazyMan {
// 抵制反射
private static boolean mark = false;
private LazyMan() {
synchronized (LazyMan.class){
if (mark == false) {
mark = true;
} else {
throw new RuntimeException("不要试图用反射破环异常");
}
}
}
// 避免指令重排 vllatile
private volatile static LazyMan lazyMan;
// 双重锁检测 DCL 懒汉式
public static LazyMan getInstance() {
if (lazyMan == null) {
synchronized(LazyMan.class){
if (lazyMan == null) {
lazyMan = new LazyMan();
// 创建对象的过程不是一个原子性操作 1. 分配内存空间 2. 执行构造方法,初始化对象
// 3. 把这个对象引用指向这个空间
}
}
}
return lazyMan;
}
}
- 静态内部类
class Hungry {
// 私有化构造器,不能new
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance() {
return HUNGRY;
}
}
常见场景:
- 在Servlet编程中,每个Servlett也是单例的
- 在Spring中,每个Bean默认就是单例的