• 设计模式 之 单例模式


    简介

    单例模式 有饿汉式 & 懒汉式 等等.

    参考链接

    https://www.bilibili.com/video/BV1K54y197iS

    饿汉式

    简单来说, 一上来就把所有的资源进行了申请, 优点, 简单. 缺点, 如果资源比较大, 容易浪费资源.

    懒汉式

    需要的时候, 才会去申请资源.

    code

    饿汉式, 非线程安全

    public class Hungry {
        private Hungry(){}
    
        private final static Hungry HUNGRY = new Hungry();
    
        public static Hungry getInstance() {
            return HUNGRY;
        }
    }
    
    

    懒汉式, 非线程安全

    public class LazyMan {
        private LazyMan(){}
    
        private static LazyMan lazyMan;
    
        private static LazyMan  getInstance() {
            if(lazyMan == null){
                lazyMan = new LazyMan(); // 需要的时候才会去申请资源.
            }
            return lazyMan;
        }
    }
    

    静态内部类实现的单例模式 非线程安全

    public class Holder {
        private Holder() {
        }
        public static Holder getInstance() {
            return InnerClass.HOLDER;
        }
    
        public static class InnerClass{
            private  static final  Holder HOLDER = new Holder();
        }
    }
    
    

    懒汉式, 线程安全

    package single;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    
    /**
     * Created by lee on 2021/5/30.
     */
    public class LazyManThread {
        private static boolean qingjiang = false;
    
        private LazyManThread(){
            synchronized (LazyManThread.class){
                if(qingjiang == false){ // 防止反射造成的单例失效.
                    qingjiang = true;
                }else{
                    throw new RuntimeException("不要试图使用反射破坏异常");
                }
                if(lazyMan != null){ // 防止反射造成的单例失效.
                    throw new RuntimeException("不要试图使用反射破坏异常");
                }
            }
            System.out.println(Thread.currentThread().getName() + "OK");
        }
    
        private static LazyManThread lazyMan;
    
        private static LazyManThread  getInstance() {
            // DCL 懒汉式  双重检测锁
            if(lazyMan == null) {
                synchronized (LazyManThread.class){ // 加锁
                    if(lazyMan == null){
                        lazyMan = new LazyManThread();
                        /*
                        * 1. 分配内存空间
                        * 2. 执行构造方法, 初始化对象
                        * 3. 把这个对象指向这个空间
                        * 123 132 由于这个顺序不一定, 也肯造成线程不安全. 使用双重锁来避免这个问题.
                        * */
                    }
                }
            }
            if(lazyMan == null){
                lazyMan = new LazyManThread();
            }
            return lazyMan;
        }
    
    //    public static void main(String[] args) {
    //        for(int i=0; i<10; i++){
    //            new Thread(()->{
    //                LazyManThread.getInstance();
    //            }).start();
    //        }
    //    }
        public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
            //LazyManThread instance = LazyManThread.getInstance();
            Field qingjiang = LazyManThread.class.getDeclaredField("qingjiang");
            qingjiang.setAccessible(true);
    
            Constructor<LazyManThread> declaredConstructor = LazyManThread.class.getDeclaredConstructor(null);
            declaredConstructor.setAccessible(true);
            LazyManThread instance2 = declaredConstructor.newInstance();
            qingjiang.set(instance2, false);
            LazyManThread instance3 = declaredConstructor.newInstance();
            //System.out.println(instance);
            System.out.println(instance2);
            System.out.println(instance3);
    
        }
    }
    
    

    TIPS

    对于使用enum的对象来说, 可以一定程度上保证进行单例模式

    package single;
    
    
    
    /**
     * Created by lee on 2021/5/30.
     */
    // enum使用
    public enum EnumSingle {
        INSTANCE;
        public EnumSingle getInstance() {
            return INSTANCE;
        }
    
    }
    class Test{
        public static void main(String[] args) {
            EnumSingle instance1 = EnumSingle.INSTANCE;
            EnumSingle instance2 = EnumSingle.INSTANCE;
    
            System.out.println(instance1);
            System.out.println(instance2);
        }
    }
    
    

    IDEA自带了一套反编译的功能, 但是不是特别好, 可以使用java 自带的反编译系统.

    javap -p XXX.class

    也不一定成功, 可以使用 jad 来进行反编译. 要下一个新代码, 比较繁琐, 暂时不测试了.

    Hope is a good thing,maybe the best of things,and no good thing ever dies.----------- Andy Dufresne
  • 相关阅读:
    C​S​S3​:​transition与visibility
    CSS ::before 和 ::after 伪元素 进阶
    [转]达梦数据库报错:不能同时包含聚集KEY和大字段(text类型)
    [转].netcore webapi post参数长度超过最大限制
    efcore执行sql查询(无需定义dbset<model>)
    Rabbitmq的死信
    用Docker搭建RabbitMq的普通集群和镜像集群
    .NetCore在IdentityServer4因为Cookies的SameSite导致授权登录跳转回登录页的问题
    2021>2022
    js 宽高相关及其应用
  • 原文地址:https://www.cnblogs.com/eat-too-much/p/14828771.html
Copyright © 2020-2023  润新知