• 深入浅出单例模式


    一、单例模式的优点:

    - 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决

    - 单例模式可以在系统设置全局的访问点,优化共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理

    二、常见的五种单例模式实现方式:

    - 主要

    • 饿汉式(线程安全,调用效率高。但是,不能延时加载。)
    • 懒汉式(线程安全,调用效率不高。但是,可以延时加载。)

    - 其他:

    • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
    • 静态内部类式(线程安全,调用效率高。可以延时加载)
    • 枚举单例(线程安全,调用效率高,不能延时加载)

      ①饿汉式实现(单例对象立即加载)

    饿汉式单例模式代码中,static变量会在类装载时初始化,此时也不会涉及多个线程对象访问该对象的问题。虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题。因此,可以省略synchronized关键字。

    问题:如果只是加载本类,而不是要调用getInstance(),甚至永远没有调用,则会造成资源浪费!

    /**
     * 饿汉式单例模式
     * @author t
     */
    public class SingletonDemo01 {
    
        private static SingletonDemo01 singletonDemo01 = new SingletonDemo01();
    
        private SingletonDemo01(){
    
        }
    
        public static SingletonDemo01 getInstance(){
            return singletonDemo01;
        }
    } 

     ②懒汉式实现(单例对象延迟加载)

    /**
     * 懒汉式单例模式
     * @author t
     */
    public class SingletonDemo02 {
    
        private static SingletonDemo02 singletonDemo02 = null;
        private SingletonDemo02(){
    
        }
    
        public static synchronized SingletonDemo02 getInstance(){
            if (singletonDemo02==null){
                singletonDemo02 = new SingletonDemo02();
            }
            return singletonDemo02;
        }
    }

      ③双重检测锁实现

      这个模式将同步内容下方到if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才同步创建了以后就没必要了

      问题:由于编译器优化原因和JVM底层内部模型原因,偶尔会出问题,不建议使用。

    /**
     * 双重检测锁实现单例模式
     * @author t
     */
    public class SingletonDemo03 {
    
        private static SingletonDemo03 singletonDemo03 = null;
        private SingletonDemo03(){
    
        }
    
        public static SingletonDemo03 getInstance(){
            if (singletonDemo03 == null){
                SingletonDemo03 sc;
                synchronized (SingletonDemo03.class){
                    sc = singletonDemo03;
                    if (sc == null){
                        synchronized (SingletonDemo03.class){
                            if (sc == null){
                                sc = new SingletonDemo03();
                            }
                        }
                        singletonDemo03 = sc;
                    }
                }
    
            }
            return singletonDemo03;
        }
    }

     ④内部类实现(懒加载)

    /**
     * 静态内部类实现单例模式(懒加载)
     * @author t
     */
    public class SingletonDemo04 {
    
        private static class SingletonClassInstance{
            private static SingletonDemo04 singletonDemo04 = new SingletonDemo04();
        }
        
        private SingletonDemo04(){
            
        }
        
        public static SingletonDemo04 getInstance(){
            return SingletonClassInstance.singletonDemo04;
        }
    }

    要点:

    外部类没有static属性,则不会像饿汉式那样立即加载对象。

    只有真正调用getInstance(),才会加载静态内部类。加载类时线程时安全的。instance时static final类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性。

    兼备了并发高效调用和延迟加载的优势

     ⑤枚举式实现

    /**
     * 枚举式实现单例模式
     * @author t
     */
    public enum SingletonDemo05 {
    
        //这个枚举元素,本身就是单例对象
        INSTANCE;
    
        public void hello(){
            System.out.println("hello");
        }
    }
  • 相关阅读:
    python csv例子
    【LR11】Error -27796: Failed to connect to server"server:port": [10060] Connection timed out错误解决办法
    LR11 scan correlation 卡死解决方案
    EC笔记:第三部分:13、以对象管理资源
    EC笔记:第二部分:12、复制对象时勿忘其每一个成分
    EC笔记:第二部分:11:在operator=中处理“自我赋值”
    EC笔记,第二部分:10.让=返回指向*this的引用
    EC笔记,第二部分:9.不在构造、析构函数中调用虚函数
    EC笔记,第二部分:8.别让异常逃离析构函数
    EC笔记,第二部分:7.为多态基类声明虚析构函数
  • 原文地址:https://www.cnblogs.com/ushowtime/p/12284352.html
Copyright © 2020-2023  润新知