解决思路
- 饿汉模式
- 懒汉模式
- 改良的懒汉模式:基于类初始化的方式(Initialization On Demand Holder Idiom)
- 双重检查锁模式(Double Checked Locking Pattern)
饿汉模式
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance() {
return instance;
}
}
特点:
- 使用静态初始化
优点:
- 实现简单
- 没有锁竞争
缺点:
- 在类被加载时就会初始化,如果加载类的目的不是获取实例(比如存在静态成员INFO,有代码调用了Singleton.INFO),就会浪费内存空间
懒汉模式
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {}
public synchronized static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
特点:
- 在调用getInstance时初始化
优点:
- 不会造成空间的浪费
- 实现也简单
缺点:
- 每次获取实例都要获取锁,浪费时间
改良版懒汉模式:基于类初始化的方式
public class LazySingleton2 {
private LazySingleton2() {}
private static class SingletonHolder {
private static LazySingleton2 instance = new LazySingleton2();
}
public static LazySingleton2 getInstance() {
return SingletonHolder.instance;
}
}
特点:
- 将实例放入静态内部类中,只有调用获取实例的方法时instance才会初始化
优点:
- 不会造成空间浪费
- 没有锁竞争
- 实现也不算复杂
缺点:
public class DclpSingleton {
private static volatile DclpSingleton instance = null;
private DclpSingleton() {}
public static DclpSingleton getInstance() {
if (instance == null) {
synchronized (DclpSingleton.class) {
if (instance == null) {
instance = new DclpSingleton();
}
}
}
return instance;
}
}
特点:
- 使用二次检查减少获取锁的次数,从而优化性能
- 必须使用volatile保证编译器不对代码执行顺序进行优化
优点:
- 惰性加载,不浪费空间
- 二次检查,思想与乐观锁类似,竞争不激烈的情况下,几乎相当于无锁
- 不会加载多余的类
缺点:
- 编码细节较之前的方法比较多
- 在Java 1.5之前不能保证功能可靠
推荐使用
- 单例类没有其他公开的静态成员或静态方法、单例一定在最开始的时候就会被加载 => 使用饿汉模式
- 其余情况 => 改良的懒汉模式
- double check细节太多,不建议使用