解决思路
- 饿汉模式
- 懒汉模式
- 改良的懒汉模式:基于类初始化的方式(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细节太多,不建议使用
