单例模式
分为饿汉模式及懒汉模式
饿汉模式是初始化时创建。
懒汉模式是使用时创建。
饿汉模式:
public class Student1 { // 2:成员变量初始化本身对象 private static Student1 student = new Student1(); // 1:构造私有 private Student1() { } // 3:对外提供公共方法获取对象 public static Student1 getSingletonInstance() { return student; } }
懒汉模式
public class Student5 { private Student5() { } /* * 此处使用一个内部类来维护单例 JVM在类加载的时候,是互斥的,所以可以由此保证线程安全 问题 */ private static class SingletonFactory { private static Student5 student = new Student5(); } /* 获取实例 */ public static Student5 getSingletonInstance() { return SingletonFactory.student; } }
饿汉模式经典的三种实现
1、双重检查锁(DCL)
public class DoubleCheckLockSingleton { private static volatile DoubleCheckLockSingleton instance; private DoubleCheckLockSingleton() {} public static DoubleCheckLockSingleton getInstance() { if (instance == null) { synchronized (DoubleCheckLockSingleton.class) { if (instance == null) { instance = new DoubleCheckLockSingleton(); } } } return instance; } public void tellEveryone() { System.out.println("This is a DoubleCheckLockSingleton " + this.hashCode()); } }
其中,synchronized防止CPU指令重排,导致极端情况下,没有初始化完成时,新的子线程就进入到synchronized后了
2、静态内部类
public class StaticInnerHolderSingleton { private static class SingletonHolder { private static final StaticInnerHolderSingleton INSTANCE = new StaticInnerHolderSingleton(); } private StaticInnerHolderSingleton() {} public static StaticInnerHolderSingleton getInstance() { return SingletonHolder.INSTANCE; } public void tellEveryone() { System.out.println("This is a StaticInnerHolderSingleton" + this.hashCode()); } }
调用StaticInnerHolderSingleton.getInstance时,内部静态类才会创建,并且线程安全
3、枚举模式
public enum EnumSingleton { INSTANCE; public void tellEveryone() { System.out.println("This is an EnumSingleton " + this.hashCode()); } }
枚举模式防止被反射攻击和序列化攻击。 因为JVM中,枚举类型不允许进行反射及序列化