一、 实现要点

1. 类只能有一个实例:类构造器私有化,只能自己创建实例
2. 类必须自行创建这个实例:使用一个静态的变量来保存唯一的实例
3. 类必须自行对外提供这个实例:类变量或静态变量get方法暴露

二、 两种模式

- 懒汉式:延迟加载对象
- 饿汉式:直接创建对象,不存在线程安全问题

三、 六种实现方式

1. 饿汉式-直接实例化(简洁直观)

/**
 * 饿汉式
 * 直接创建
 * (1)构造器私有化
 * (2)自行创建,并使用静态变量保存
 * (3)提供对外方法
 */
public class Singleton_eh1 {
    private static final Singleton_eh1 INSTANCE = new Singleton_eh1();
    private Singleton_eh1(){}
    public static Singleton_eh1 getInstance(){
        return INSTANCE;
    }
}

2. 饿汉式-枚举式(最简洁)

/**
 * 饿汉式
 * 枚举类型:表示该类的对象是有限的几个
 * 直接定义为一个,就成为了单例
 */
public enum Singleton_eh2 {
     INSTANCE
}

3. 饿汉式-静态代码块(适合复杂实例化)

/**
 * 饿汉式
 * 静态内部类
 */
public class Singleton_eh3 {
    private static final Singleton_eh3 INSTANCE;
    static {
        /**
         * 适合复杂的实例化,例如实例化类时加载一些外部的文件等
         */
        INSTANCE = new Singleton_eh3();
    }

    private Singleton_eh3(){}

    public static Singleton_eh3 getInstance(){
        return INSTANCE;
    }
}

4. 懒汉式-线程不安全(适用于单线程)

/**
 * 懒汉式:多线程线程不安全
 */
public class Singleton_lh1 {
    private static Singleton_lh1 instance;
    private Singleton_lh1(){}
    public static Singleton_lh1 getInstance(){
        if (instance == null) {
            instance = new Singleton_lh1();
        }
        return instance;
    }
}

5. 懒汉式-线程安全(适用于多线程)

/**
 * 懒汉式:多线程线程安全
 */
public class Singleton_lh2 {
    private static Singleton_lh2 instance;
    private Singleton_lh2(){}
    public static Singleton_lh2 getInstance(){
        //外层if判断不加也能保证线程安全,加上可以提升性能
        if (instance == null) {
            synchronized (Singleton_lh2.class) {
                if (instance == null) {
                    instance = new Singleton_lh2();
                }
            } 
        }
        return instance;
    }
}

6. 懒汉式-静态内部类形式(适用于多线程)

/**
 * 懒汉式:静态内部类:静态内部类在类加载时不会初始化,调用时初始化
 * 因为是静态的,所以只会存在一个实例
 * 多线程线程安全
 */
public class Singleton_lh3 {
    private Singleton_lh3(){}

    private static class Inner{
        private static final Singleton_lh3 INSTANCE = new Singleton_lh3();
    }

    public static Singleton_lh3 getInstance(){
        return Inner.INSTANCE;
    }
}