(Singleton Pattern)单例模式,该类负责确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式的结构

单例模式的主要有以下角色:

单例模式的实现

单例设计模式分类两种:

**懒汉式:**类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建

**饿汉式:**类加载就会导致该单实例对象被创建

饿汉式(静态变量)

class SingleTon {
    private SingleTon() {};

    private static SingleTon instance = new SingleTon();

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

饿汉式(静态代码块)

class SingleTon {
    private SingleTon() {}

    private static SingleTon instance;

    static {
        instance = new SingleTon();
    }

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

懒汉式(静态内部类方式)

class SingleTon {
    private SingleTon() {}

    private static class SingletonHolder {
        private static final SingleTon INSTANCE = new SingleTon();
    }

    public static SingleTon getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

第一次加载Singleton类时不会去初始化INSTANCE,只有第一次调用getInstance,虚拟机加载SingletonHolder并初始化INSTANCE,这样不仅能确保线程安全,也能保证 Singleton 类的唯一性。

懒汉式(双重检查锁)

class SingleTon {
    private SingleTon() {}

    private static volatile SingleTon instance;

    public static SingleTon getInstance() {
        if(instance == null) {
            synchronized (SingleTon.class) {
                if(instance == null) {
                    instance = new SingleTon();
                }
            }
        }
        return instance;
    }
}

双重检查锁模式是一种非常好的单例实现模式,解决了单例、性能、线程安全问题,上面的双重检测锁模式看上去完美无缺,其实是存在问题,在多线程的情况下,可能会出现空指针问题,出现问题的原因是JVM在实例化对象的时候会进行优化和指令重排序操作。

要解决双重检查锁模式带来空指针异常的问题,只需要使用 volatile 关键字, volatile 关键字可以保证可见性和有序性。