• 彻底玩转单例模式


    彻底玩转单例模式

    DCL懒汉式

    使用双重检查懒汉式时为什么要使用volatile

    public class LazyMan {
        private static LazyMan lazyMan;
    
        private LazyMan() {
        }
    
        //双重检测模式的懒汉式单例
        public static LazyMan getInstance(){
            if (lazyMan==null){
                synchronized (LazyMan.class){
                    if (lazyMan==null){
                        lazyMan = new LazyMan();    //不是一个原子性操作
                        /**
                         * 1. 分配内存空间
                         * 2、执行构造方法,初始化对象
                         * 3、把这个对象指向这个空间
                         *
                         * 123
                         * 132 A
                         *     B // 此时lazyMan还没有完成构造
                         *     若发生这样的指令重排则在多线程时可能会返回空对象,尽管可能性非常小
                         */
                    }
                }
            }
            return lazyMan;
        }
    }
    

    静态内部类

    // 静态内部类
    public class Holder {
        private Holder(){
    
        }
    
        public static Holder getInstace(){
            return InnerClass.HOLDER;
        }java
    
        public static class InnerClass{
            private static final Holder HOLDER = new Holder();
        }
    
    }
    

    反射会破坏单例模式

    // 懒汉式单例
    // 道高一尺,魔高一丈!
    public class LazyMan {
    
        private static boolean is_exist = false;
    	//设置标志位来检测构造器是否被执行过,来避免反射破坏单例
        //但是,当标志位被其他人知道后,任然可以通过main方法中被注释的代码
        //先修改标志位再通过反射获取新的对象。
        //所谓道高一尺魔高一丈。
        private LazyMan(){
            synchronized (LazyMan.class){
                if (is_exist == false){
                    is_exist = true;
                }else {
                    throw new RuntimeException("不要试图使用反射破坏异常");
                }
            }
        }
    
        private volatile static LazyMan lazyMan;
    
        // 双重检测锁模式的 懒汉式单例  DCL懒汉式
        public static LazyMan getInstance(){
            if (lazyMan==null){
                synchronized (LazyMan.class){
                    if (lazyMan==null){
                        lazyMan = new LazyMan(); // 不是一个原子性操作
                    }
                }
            }
            return lazyMan;
        }
    
        // 反射!
        public static void main(String[] args) throws Exception {
    //        LazyMan instance = LazyMan.getInstance();
    
            //Field is_exist = LazyMan.class.getDeclaredField("is_exist");
            //is_exist.setAccessible(true);
    
            Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
            declaredConstructor.setAccessible(true);
            LazyMan instance = declaredConstructor.newInstance();
    
            //is_exist.set(instance,false);
    
            LazyMan instance2 = declaredConstructor.newInstance();
    
            System.out.println(instance);
            System.out.println(instance2);
        }
    
    }
    

    枚举单例

    枚举可以保证不被反射

    public enum EnumSingle {
    
        INSTANCE;
    
        public EnumSingle getInstance(){
            return INSTANCE;
        }
    
    }
    
    class Test{
    
        public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            EnumSingle instance1 = EnumSingle.INSTANCE;
            Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
            declaredConstructor.setAccessible(true);
            EnumSingle instance2 = declaredConstructor.newInstance();
    
            // NoSuchMethodException: com.maple.single.EnumSingle.<init>()
            System.out.println(instance1);
            System.out.println(instance2);
    
        }
    
    }
    

    枚举的反编译代码

    public final class EnumSingle extends Enum
    {
        public static EnumSingle[] values()
        {
            return (EnumSingle[])$VALUES.clone();
        }
        public static EnumSingle valueOf(String name)
        {
            return (EnumSingle)Enum.valueOf(com/maple/single/EnumSingle, name);
        }
        //没有无参构造器,只有一个2参构造器
        private EnumSingle(String s, int i)
        {
            super(s, i);
        }
        public EnumSingle getInstance()
        {
            return INSTANCE;
        }
        public static final EnumSingle INSTANCE;
        private static final EnumSingle $VALUES[];
        static
        {
            INSTANCE = new EnumSingle("INSTANCE", 0);
            $VALUES = (new EnumSingle[] {
                    INSTANCE
            });
        }
    }
    

    视频参考https://www.bilibili.com/video/BV1B7411L7tE
    上一篇:Volatile
    下一篇:理解CAS

  • 相关阅读:
    eclipse对项目Working Sets整理分类
    word中visio只显示边框,不显示内容解决
    使用WebStorm运行vue项目
    如何提高你的学习速度-超链接式学习法
    SQL中的join连接查询
    TCP的三次握手
    Tomcat 实现热部署
    Linux下软件设成系统服务运行
    Redis服务器搭建
    nginx.conf完整配置实例
  • 原文地址:https://www.cnblogs.com/junlinsky/p/13443368.html
Copyright © 2020-2023  润新知