【设计模式】- 单例模式

【设计模式】- 单例模式

饿汉式单例模式

类加载时就已实例化

public class HungrySingleton {
    private static final HungrySingleton instance = new HungrySingleton(); 

    private HungrySingleton() {}

    public static HungrySingleton getInstance() {
        return instance;
    }
}

最简单的单例模式

  • 类的静态变量只初始化一次,JVM的类加载机制保证了线程安全
  • private修饰构造器,防止new创建对象
  • 调用getInstance()静态方法获得该类的唯一实例

懒汉式单例模式(双重检查锁模式)

懒汉式都是使用时才实例化对象

public class LazySingleton {
    
    private static volatile LazySingleton instance;
    
    private LazySingleton () {}
    
    public static LazySingleton getInstance() {
        if (instance == null) {
            synchronized(LazySingleton.class) {
                if (instance == null) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    } 
}
  • volatile关键字禁止指令重排,用于保证线程安全
  • private修饰构造函数,防止new创建对象
  • synchronized关键字保证线程安全,放在方法中,可以优化性能(不直接修饰方法)

为什么要有两重验证?

第一重验证,大部分线程直接返回实例。如果没有第一重验证,每个线程都需要锁判断,效率很低。
第二重验证保证单例的实现。如果没有第二重验证,假设现在有两条线程,线程A在第一重验证处停下,此时线程B获得CPU时间片,开始执行,并且拿到了这把锁,实例化一个对象,然后释放锁。线程A拿到这把锁,也实例化了一个对象,这两个对象肯定是不同的。

懒汉单例模式(静态内部类实现)

比较完美的一种单例模式实现

public class InnerClassSingleton {

    private InnerClassSingleton() {}

    private static class InstanceHolder {
        private final static InnerClassSingleton instance = new InnerClassSingleton();
    }

    public static InnerClassSingleton getInstance() {
        return InstanceHolder.instance;
    }
}

  • JVM加载外部类时不会加载静态内部类
  • 只有当调用内部类的属性时,JVM才加载该类,并初始化它的属性

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×