1. 简单实用的方法
public class Singleton1 {
    private static final Singleton1 INSTANCE = new Singleton1();
    private Singleton1() {
        System.out.println("init");
    }
    public static Singleton1 getInstance() {
        return INSTANCE;
    }
}
  • jvm 保证了java 初始化一次class
  • static 又保证了类在被加载完后立马初始化static 变量。
  • 例如vertx框架中 vertx.vert 就是这么实现的单例。
  • 缺点:不管用不用都会被实例化(个人看法写出来就是给我用的,还能加加快真正使用时的实例化时间,多好)
  1. lazy加载模式
public class Singleton2 {
    private static Singleton2 INSTANCE ;
    private Singleton2() {
        System.out.println("init");
    }
    public static Singleton2 getInstance() {
       if(INSTANCE==null){
           INSTANCE = new Singleton2();
       }
       return INSTANCE;
    }
}
  • 懒加载模式 需要的时候再去初始化他,但是这样并不是线程安全的
  • 解决方案方法上加synchronized锁即可,但是效率会变低。
  1. 双重判断锁
public class Singleton3 {
    private static volatile Singleton3 INSTANCE; // volatile 防止指令重排序 

    private Singleton3() {
        System.out.println("init");
    }

    public static Singleton3 getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton3.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton3();
                }
            }
        }
        return INSTANCE;
    }
}
  • 有点啰嗦。
  1. 静态内部类初始化
public class Singleton4 {
    private Singleton4() {
        System.out.println("init");
    }
    public static Singleton4 getInstance() {
        return SingletonHolder.INSTANCE;
    }
    private static class SingletonHolder{
        private static final Singleton4 INSTANCE = new Singleton4();
    }
}
  • 利用jvm 特性起java 只会初始化 Singleton4,不会初始化内部类,等真的要用的时候才会去初始化对象。
  1. 枚举类保证单例
public enum Singleton5 {
    INSTANCE;
}
  • jvm 特性枚举 类都是单例的