单例模式
我们在单例类中添加一个该类的成员属性Instance,并提供一个getInstance方法访问它。一般来说,有如下几种实现。
-
饿汉式
这里的单例,是由JVM加载类时初始化生成的单例,由JVM保证了线程安全。但是耗资源,起步慢。
public class HungrySingleton { private static HungrySingleton instance = new HungrySingleton(); public static HungrySingleton getInstance(){ return instance; } private HungrySingleton(){} }
-
懒汉式
不是在类加载时生成,所以需要我们自己通过同步保证线程安全。通常用双重校验锁实现,是写法最复杂的方式。
public class DoubleLockSingleton { private static volatile DoubleLockSingleton instance; public static DoubleLockSingleton getInstance() { if(instance == null){ synchronized (DoubleLockSingleton.class) { if(instance == null) { instance = new DoubleLockSingleton(); } } } return instance; } private DoubleLockSingleton() { } }
-
静态内部类实现
也是懒汉式的,写法很简洁,个人觉得是最推荐的写法。同时它也是线程安全的,因为单例是在嵌套类被加载时生成的。
public class StaticInnerSingleton { private static class Holder{ private static StaticInnerSingleton instance = new StaticInnerSingleton(); } public static StaticInnerSingleton getInstance(){ return Holder.instance; // 执行到这时才会加载Holder嵌套类。 } private StaticInnerSingleton(){ } }
-
枚举类
枚举自身的特性,JVM会保证线程安全和单一实例。它也是饿汉式的,枚举类加载时就会创建单例。枚举最大的优点在于可以预防反射导致的多例,因为反射无法作用于枚举类。
public enum EnumSingleton { INSTANCE; // 枚举类的构造函数默认是private的 EnumSingleton(){} public void doSomething() { // 这个类的其他方法 } } // 使用时直接 EnumSingleton.INSTANCE 就获取到了该类的单例。