普通的两种单例模式,饿汉式和懒汉式
饿汉式会造成内存的占用
// 首先私有构造 private HunSingle(){} private static final HunSingle HUN_SINGLE = new HunSingle(); public static HunSingle getInstance(){ return HUN_SINGLE; }懒汉式
private LazySingleDemo1(){} # 加上volatile关键字是保证不会发生指令重排,因为new LazySingleDemo1();不是原子操作。 private volatile static LazySingleDemo1 singleDemo1; public static LazySingleDemo1 getInstance() { if (singleDemo1 == null) { synchronized (LazySingleDemo1.class) { if (singleDemo1 == null) { singleDemo1 = new LazySingleDemo1(); } } } return singleDemo1; }静态内部类实现
public class InnerStaticSingle { private InnerStaticSingle(){} public static InnerStaticSingle getInstance() { return InnerSingle.INNER_STATIC_SINGLE; } public static class InnerSingle{ private static final InnerStaticSingle INNER_STATIC_SINGLE = new InnerStaticSingle(); } }但是上边的这种会有反射导致的安全问题,就不是单例了。
/** * @Description: 私有构造方法 * @author libiao * @Date 2020-10-22 11:15 * @Param * @return **/ private LazySingleDemo1(){ synchronized (LazySingleDemo1.class) { if (singleDemo1 != null) { throw new RuntimeException("不要用反射"); } } } private volatile static LazySingleDemo1 singleDemo1; public static LazySingleDemo1 getInstance() { if (singleDemo1 == null) { synchronized (LazySingleDemo1.class) { if (singleDemo1 == null) { singleDemo1 = new LazySingleDemo1(); } } } return singleDemo1; } public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { LazySingleDemo1 instance = LazySingleDemo1.getInstance(); System.out.println(instance); // 使用反射 Constructor<LazySingleDemo1> constructor = LazySingleDemo1.class.getDeclaredConstructor(null); constructor.setAccessible(true); LazySingleDemo1 lazySingleDemo1 = constructor.newInstance(); System.out.println(lazySingleDemo1); }上边在构造方法中加上if判断还是会存在问题,因为可以都用反射来创建对象。用反射那么singleDemo1变量就用不到,就会永远为空,可以用标志位来解决,但是任然不够安全。因为可以反编译。
反射是不能破坏枚举的
@SuppressWarnings("all") public enum EnumSingle { INSTANCE; } class test{ public static void main(String[] args) { EnumSingle instance = EnumSingle.INSTANCE; EnumSingle instance1 = EnumSingle.INSTANCE; System.out.println(instance); System.out.println(instance1); } }