设计模式之单例模式 DCL双重检测 实例化Volatile防止指令排序 synchronized方法块线程安全 反射安全性问题分析

单例模式之饿汉式模式

  • 饿汉式模式来历 直接实例化犹如饿汉子尽快想把饭吃完故称为饿汉式
public class Hungry{
    public static final Hungry hungry = new Hungry();
    
    private Hungry(){}

    private static final Hungry getInstance{
      return hungry;
    }
}

单例模式之懒汉式模式

  • 懒汉式模式来历 延迟实例化,懒加载故称为懒汉式
public class LayMan{
    public static volatile  LayMan layMan = null;
    
    private LayMan(){}

    //DCL双重检测 + synchronized
    private static LayMan getInstance(){
      if(layMan!=null){
          synchronized (layMan.class){
            if(layMan != null){
              layMan = new LayMan();  //不是原子的操作,需要在  volatile 防止指令重排序
            }
          }
      }
      return layMan;
    }
}

单例模式之静态类实现模式

  • 静态类单例模式
package com.gof23.single1;

import com.gof23.single.StaticClass;

public class StaticClass1 {
    private StaticClass1(){

    }
    private static class InnerClass{
        private static StaticClass1 staticClass1 = new StaticClass1();
    }
    private static StaticClass1 getInstance(){
        return InnerClass.staticClass1;
    }

    public static void main(String[] args) {
        StaticClass1 s1 = StaticClass1.getInstance();
        StaticClass1 s2 = StaticClass1.getInstance();

        System.out.println(s1 == s2);
    }
}

单例模式之枚举类实现模式

  • 枚举单例模式
package com.gof23.single;
import sun.security.jca.GetInstance;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public enum EnumInstance {
    INSTANCE;

    private static EnumInstance getInstance(){
        return INSTANCE;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        EnumInstance instance1 =  EnumInstance.getInstance();
        EnumInstance instance2 =  EnumInstance.getInstance();
        System.out.println(instance1);
        System.out.println(instance2);

        Constructor constructor = instance1.getClass().getDeclaredConstructor();
        constructor.setAccessible(true); //测试反射安全性问题
        EnumInstance instance3 = (EnumInstance) constructor.newInstance();
        System.out.println(instance3);
    }
}

小结: 1. 单例模式都会反射安全性问题,通过反射构造器newInstance会破坏单例模式
2. enum枚举类单例模式不存在反射安全性问题

posted @ 2021-09-28 19:53  回望初心  阅读(54)  评论(0)    收藏  举报