美文网首页
2、创建型设计模式-单例设计模式

2、创建型设计模式-单例设计模式

作者: 日落_3d9f | 来源:发表于2021-05-10 11:33 被阅读0次

    江湖传言里的设计模式-单例设计模式

    简介:什么是单例设计模式和应用

    • 备注:面试重点考查

    • 单例设计模式:

      • 这个是最简单的设计模式,所以拎出来第一个讲, 但事实却不是。
      • 单例意思只包含一个对象被称为单例的特殊类
      • 通过单例模式可以保证系统中,应用该模式的类只有一个对象实例
    • 使用场景

      • 业务系统全局只需要一个对象实例,比如发号器、redis连接对象等
      • Spring IOC容器中的bean默认就是单例
      • spring boot 中的controller、service、dao层中通过@autowire的依赖注入对象默认都是单例的
    • 分类:

      • 懒汉:就是所谓的懒加载,延迟创建对象
      • 饿汉:与懒汉相反,提前创建对象
    • 实现步骤

      • 私有化构造函数
      • 提供获取单例的方法
    单例设计模式

    单例模式中的懒汉实现+双重检查锁定+内存模型

    代码:

    package net.xdclass;
    
    /**
     * @Description 单例设计模式 - 懒汉实现方式
     * @Author 二当家小D
     * @Remark 
     * @Version 1.0
     **/
    
    public class SingletonLazy {
        private static SingletonLazy instance;
    
        /**
         * 构造函数私有化
         */
        private SingletonLazy(){}
    
        /**
         * 单例对象的方法
         */
        public void process(){
            System.out.println("方法调用成功");
        }
    
        /**
         * 第一种方式
         * 对外暴露一个方法获取类的对象
         *
         * 线程不安全,多线程下存在安全问题
         *
         */
        public static SingletonLazy getInstance(){
            if(instance == null){
                instance = new SingletonLazy();
            }
            return instance;
        }
    
    
        /**
         * 第二种实现方式
         *  通过加锁 synchronized 保证单例
         *
         * 采用synchronized 对方法加锁有很大的性能开销
         *
         * 解决办法:锁粒度不要这么大
         *
         * @return
         */
        public static synchronized SingletonLazy getInstance(){
            if(instance == null){
                instance = new SingletonLazy();
            }
            return instance;
        }
    
    
        /**
         * 第三种实现方式 也不可以,存在重复建对象
         * @return
         */
        public static  SingletonLazy getInstance(){
            if(instance == null){
                // A、B
                synchronized (SingletonLazy.class){
                    instance = new SingletonLazy();
                }
            }
            return instance;
        }
    
        /**
         * 第四种实现方式
         *
         * DCL 双重检查锁定 (Double-Checked-Locking),在多线程情况下保持高性能
         *
         * 这是否安全,instance = new SingletonLazy(); 并不是原子性操作
         * 1、分配空间给对象
         * 2、在空间内创建对象
         * 3、将对象赋值给引用instance
         *
         * 假如线程 1-》3-》2顺序,会把值写会主内存,其他线程就会读取到instance最新的值,但是这个是不完全的对象
         * (指令重排)
         * @return
         */
        public static  SingletonLazy getInstance(){
            if(instance == null){
                // A、B
                synchronized (SingletonLazy.class){
                    if(instance == null) {
                        instance = new SingletonLazy();
                    }
                }
            }
            return instance;
        }
    
        /**
         * volatile是Java提供的关键字,它具有可见性和有序性,
         *
         * 指令重排序是JVM对语句执行的优化,只要语句间没有依赖,那JVM就有权对语句进行优化
         *
         * 禁止了指令重排
         */
        private static volatile SingletonLazy instance;
        public static  SingletonLazy getInstance(){
            //第一重检查
            if(instance == null){
                // A、B ,锁定
                synchronized (SingletonLazy.class){
                    //第二重检查
                    if(instance == null) {
                        instance = new SingletonLazy();
                    }
                }
            }
            return instance;
        }
    
    }
    

    主代码:

    public class Main {
    
        public static void main(String[] args) {
            SingletonLazy.getInstance().process();
        }
    }
    

    单例模式中的懒汉实现+双重检查锁定+内存模型

    饿汉设计模式:

    • 饿汉方式:提前创建好对象
    • 优点:实现简单,没有多线程同步问题
    • 缺点:不管有没使用,instance对象一直占着这段内存

    如何选择:

    • 如果对象不大,且创建不复杂,直接用饿汉的方式即可
    • 其他情况则采用懒汉实现方式

    代码:

    public class SingletonHungry {
        private static SingletonHungry instance = new SingletonHungry();
    
        private SingletonHungry(){}
    
        public static SingletonHungry getInstance(){
            return instance;
        }
    
        /**
         * 单例对象的方法
         */
        public void process(){
            System.out.println("方法调用成功");
        }
    
    }
    
    ``
    Main代码:
    

    public class Main {
    public static void main(String[] args) {
    //SingletonLazy.getInstance().process();
    SingletonHungry.getInstance().process();
    }
    }

    ``

    单例设计模式在JDK源码里面的应用

    • JDK中Runtime类 饿汉方式
    JDK中Runtime类 饿汉方式

    Runtime类用于表示虚拟机运行时的状态, 用于封装JVM虚拟机进程。每次启动虚拟机都对应一个Runtime实例, 且只有一个实例。因为该类采用单例模式设计, 对象不可以直接实例化. 所以要想获得一个Runtime实例, 只能通过如下方式:

    Runtime rt = Runtime.getRuntime();

    示例代码:

    public static void main(String[] args) {
        // 获取Runtime实例对象
        Runtime rt = Runtime.getRuntime();
        System.out.println("处理器个数: "+rt.availableProcessors());
        System.out.println("空闲内存M数: "+rt.freeMemory()/1024/1024);
        System.out.println("最大可用内存M数: "+rt.maxMemory()/1024/1024);
    }
    
    • JDK中Desktop类 懒汉方式
    懒汉方式

    相关文章

      网友评论

          本文标题:2、创建型设计模式-单例设计模式

          本文链接:https://www.haomeiwen.com/subject/spvbdltx.html