• 大话设计模式:单例模式


    单例模式是就是在系统运行时,我们希望类生成的对象就一个,类实例化只能时一样,比如线程池、缓存等,我们在系统运行如果缓存或线程池变化,可能会造成系统出现异常,资源过度浪费。

    单例模式的定义:

        确保一个类只能有一个实例,并提供一个全局访问点。

    单例模式分为两种,一种是不安全的单例模式(我们需要废弃),第二种是线程安全的单例模式。下面列举几种单例模式的实现。

    1。饿汉式
    2。同步方法-懒汉式
    3。同步代码块-懒汉式
    4。双重检查锁
    5。枚举类
    6。静态内部类
    7。静态枚举类
    ---
    使用单例模式注意三大条件:
    1.私有化构造器,
    2.类含有静态私有对象,
    3.提供公共静态的方法创建或获取私有对象的值。
    ---
    使用单例
    优点:
    1.在内存中只有一个实例对象,减少频繁创建销毁对象实例的内存开销;
    2.避免对资源的过度占用。
    缺点:
    没有接口,不能继承,与单一职责原则冲突,一个类只应该关系内部逻辑而不应该关系外部怎样实例化。
    使用场景:
    1.唯一的序列号
    2.WEB中的计数器
    3.创建一个对象消耗的资源过多

    1. 饿汉式代码

    /**
     * 单例模式:饿汉式
     */
    public class SingletonDemo01 {
    
        //类初始化立即加载,由于类加载时完成初始化,线程安全。不用同步快,调用效率高。
        private static SingletonDemo01 instance = new SingletonDemo01();
    
        private SingletonDemo01() {
    
        }
    
        public static SingletonDemo01 getInstance() {
            return instance;
        }
    }

    2. 懒汉式 同步方法

    /**
     * 单例模式:懒汉式线程安全
     */
    public class SingletonDemo03 {
    
        //类初始化延迟加载,方法同步线程安全,调用效率低。
        private static SingletonDemo03 instance = null;
    
        private SingletonDemo03() {
        }
    
        public static synchronized SingletonDemo03 getInstance() {
    
            if (instance == null) {
                instance = new SingletonDemo03();
            }
            return instance;
        }
    }

    3. 懒汉式同步方法

    /**
     * 单例模式:懒汉式双重检查锁
     */
    public class SingletonDemo04 {
    
        //由于编译器优化和JVM内部模型原因,同步块会有问题,会出现问题
        private static SingletonDemo04 instance = null;
    
        private SingletonDemo04() {
    
        }
    
        public static SingletonDemo04 getInstance() {
    
            if (instance == null) {
                synchronized (SingletonDemo04.class) {
                    if (instance == null) {
                        instance = new SingletonDemo04();
                    }
                }
    
            }
            return instance;
        }
    }

    4.静态内部类

    /**
     * 单例模式:静态内部类懒加载
     */
    public class SingletonDemo05 {
    
        //外部没有static属性,不会立即加载对象
        //真正调用getInstance,才会加载内部类
        //高效+安全+延迟加载
        private static class SingletonInstance {
            public static SingletonDemo05 instance = new SingletonDemo05();
        }
    
        private SingletonDemo05() {
    
        }
    
        public static SingletonDemo05 getInstance() {
            return SingletonInstance.instance;
        }
    }

    5. 枚举类

    /**
     * 单例模式:枚举类
     */
    public enum SingletonDemo06 {
        //直接用SingletonDemo06.INSTANCE本身代理,代表一个对象
        //避免反射、反序列化,效率高
        //没有懒加载
       INSTANCE;
       Enum ss;
    }

    6. 枚举类实现懒加载

    /**
     * 单例模式:枚举类实现懒加载
     */
    public class SingletonDemo08 {
    
        // 私有构造函数
        private SingletonDemo08() {
    
        }
    
        public static SingletonDemo08 getInstance() {
            return Singleton.INSTANCE.getInstance();
        }
    
        private enum Singleton {
            INSTANCE;
    
            private SingletonDemo08 singleton;
    
            // JVM保证这个方法绝对只调用一次
            Singleton() {
                singleton = new SingletonDemo08();
            }
    
            public SingletonDemo08 getInstance() {
                return singleton;
            }
        }
    }

    7.解决反射漏铜和序列化漏铜

    import java.io.ObjectStreamException;
    import java.io.Serializable;
    
    /**
     * 单例模式:解决反射漏铜,通过设置constructor.setAccessible(true);//跳过权限校验,是的创建实例不一致
     *           解决序列化漏铜,readResolve()
     */
    public class SingletonDemo07 implements Serializable {
    
        //类初始化延迟加载,方法同步线程安全,调用效率低。
        private static SingletonDemo07 instance = null;
    
        private SingletonDemo07() {
            if (instance != null) {//防止通过反射破解单例
                throw new RuntimeException();
            }
        }
    
        public static synchronized SingletonDemo07 getInstance() {
    
            if (instance == null) {
                instance = new SingletonDemo07();
            }
            return instance;
        }
    
        //反序列化时,直接返回此对象,而不生成新对象
        private Object readResolve() throws ObjectStreamException {
            return instance;
        }
    }
  • 相关阅读:
    合格linux运维人员必会的30道shell编程实践题及讲解
    合格linux运维人员必会的30道shell编程实践题及讲解-13
    合格linux运维人员必会的30道shell编程实践题及讲解-12
    合格linux运维人员必会的30道shell编程实践题及讲解-11
    合格linux运维人员必会的30道shell编程实践题及讲解-10
    合格linux运维人员必会的30道shell编程实践题及讲解-09
    学习Vim的四周计划
    Linux shell 逻辑运算符、逻辑表达式详解
    60个DevOps开源工具,你在用哪些?
    误删重要文件怎么办?学会Linux 救援模式再也不担心
  • 原文地址:https://www.cnblogs.com/dc-earl/p/11141927.html
Copyright © 2020-2023  润新知