面试题答案
一键面试问题产生原因
在多线程环境下,当多个线程同时访问懒汉式单例模式的getInstance
方法时,由于该方法在实例未创建时会进行实例化操作。如果多个线程同时判断实例为空,就会各自创建一个实例,导致单例模式失效,破坏了单例的唯一性。
优化方案
- 饿汉式单例
- 实现代码
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
- **优点**:线程安全,在类加载时就创建实例,避免了多线程竞争问题。
- **缺点**:不管是否使用该实例,类加载时就会创建,可能造成资源浪费。
2. 静态内部类单例 - 实现代码
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
- **优点**:线程安全,延迟加载,只有在调用`getInstance`方法时才会加载内部类并创建实例。
- **缺点**:相比其他简单实现,代码结构稍复杂。
3. 双重检查锁定(DCL) - 实现代码
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
- **优点**:延迟加载,线程安全,在第一次检查实例为空时才进行同步操作,提高了性能。
- **缺点**:实现较复杂,需要注意`volatile`关键字的使用,防止指令重排导致获取到未初始化完全的实例。