单例模式
1. 饿汉式
- 饿汉式在类加载时就初始化完成创建一个对象供外部使用,该方法线程安全,但无法防止反射创建新对象
public class SingleHungry { private static SingleObject obj = new SingleObject(); /** * 注意:单例模式的构造方法必须是private */ private SingleHungry() { } public static SingleObject getInstance() { return obj; } }
2. 懒汉式
- 采用了延迟加载方式避免了空间的浪费,该方法需要加锁来保证线程安全,该方式同样无法防止其他人用反射创建对象
public class SingleLazy { //延迟加载 private static SingleObject obj = null; private SingleLazy() { } /** * 双重检查所来确保线程安全并且只创建一个对象 */ public static SingleObject getInstance() { if(obj == null) { synchronized (SingleLazy.class) { if(obj == null) { obj = new SingleObject(); } } } return obj; } }
3. 静态内部类
- 该方法既保证线程安全也确保只有一个对象创建, 仍然无法避免通过反射创建对象
public class SingleInner { private static class InnerClass { private static SingleObject obj = new SingleObject(); } private SingleInner() { } /** * 只有当运行该方法时才会去加载InnerClass类并且初始化对象 * 这样保证了线程安全: * 虚拟机会保证一个类的类初始化阶段在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类, * 那么只会有一个线程去执行这个类的类初始化方法,其他线程都需要阻塞等待,直到活动线程执行完毕。 * 同一个加载器下,一个类型只会类初始化一次。 */ private static SingleObject getInstance() { return InnerClass.obj; } }
4. 枚举
- 保证了线程安全且只创建一个对象,避免了被反射攻击
public class SingleEnum { //创建内部枚举类 private enum EnumSingle { SINGLETON; private SingleObject single; private EnumSingle() { single = new SingleObject(); } public SingleObject getInstance() { return single; } } public static SingleObject getInstance() { return EnumSingle.SINGLETON.getInstance(); } }