• 设计模式之单例模式


    一、单例模式的特点:

    • 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例

    二、常见的几种单例模式

    1、饿汉式,静态常量

    • 在类装载时就完成类的初始化,没有达到lazy loading的效果,如果从始至终没有使用过这个类,可能造成内存浪费。
    • 避免了多线程同步问题
    public class Singleton01 {
    
        private final static Singleton01 instance = new Singleton01();
    
        //构造器私有化(防止new)
        private Singleton01() {
        }
    
        public static Singleton01 getInstance() {
            return instance;
        }
    } 

    2、饿汉式,静态代码块

    • 将类实例化的过程放在了静态代码块中,也是在类装载的时候就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的
    public class Singleton02 {
    
        private static Singleton02 instance;
    
        //在静态代码块中创建单例对象
        static {
            instance = new Singleton02();
        }
    
        private Singleton02() {
        }
    
        public static Singleton02 getInstance() {
            return instance;
        }
    }  

    3、懒汉式,线程不安全(不推荐使用)

    • 只能在单线程下使用。
    • 多线程下,一个线程进入了if(singleton==null) 判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。
    public class Singleton03 {
    
        //声明类的唯一实例
        private static Singleton03 instance;
    
        //造方法私有化,不允许外部直接创建对象
        private Singleton03() {
        }
    
        //当使用到getInstance()方法时,才去创建该对象
        public static Singleton03 getInstance() {
            if (instance == null) {
                instance = new Singleton03();
            }
            return instance;
        }
    }  

    4、懒汉式,线程安全(不推荐使用)

    • 问题:效率太低,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步
    public class Singleton04 {
    
        //声明类的唯一实例
        private static Singleton04 instance;
    
        //造方法私有化,不允许外部直接创建对象
        private Singleton04() {
        }
    
        //当使用到getInstance()方法时,才去创建该对象
        public synchronized static Singleton04 getInstance() {
            if (instance == null) {
                instance = new Singleton04();
            }
            return instance;
        }
    
    } 

    5、DCL双重检锁机制(Double Check Lock)【推荐使用】

    • 两次检查instance == null,一次是在同步块外,一次是在同步块内。第一次检查instance不为null,那么就不需要执行下面的加锁和初始化操作。可以大幅降低synchronized带来的性能开销。
    • 使用volatile禁止指令重排序,对volatile变量的写操作都先行发生于后面对这个变量的读操作
    class Singleton05 {
    
        private static volatile Singleton05 instance;
    
        private Singleton05() {
            System.out.println(Thread.currentThread().getName() + " 构造方法SingletonDemo");
        }
    
        //解决线程安全问题,解决懒加载问题,同时保证了效率
        public static Singleton05 getInstance() {
            if (instance == null) {
                synchronized (Singleton05.class) {
                    if (instance == null) {
                        instance = new Singleton05();
                    }
                }
            }
            return instance;
        }
    } 

    6、静态内部类(推荐使用)

    • 采用了类装载的机制来保证初始化实例时只有一个线程。
    • Singleton07类装载时,不会导致静态内部类被装载,当调用getInstance()方法时,静态内部类会装载,而且只装载一次,并且是线程安全的
    • 避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
    public class Singleton06 {
    
        private static class SingletonInstance {
            private static final Singleton06 INSTANCE = new Singleton06();
        }
    
        //构造器私有化
        private Singleton06() {
        }
    
        public static final Singleton06 getInstance() {
            return SingletonInstance.INSTANCE;
        }
    }

    7、枚举(推荐使用)

    • 不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
    public enum Singleton07 {
        INSTANCE;
    }  

    总结:

    一般情况下直接使用饿汉式就好了,
    如果明确要求要懒加载(lazy initialization)会倾向于使用静态内部类,
    如果涉及到反序列化创建对象时会试着使用枚举的方式来实现单例

    三、单例模式的使用场景:

    需要频繁创建和销毁的对象

    创建对象耗时过多或耗费资源过多,但又经常用到的对象

    频繁访问数据库或文件的对象(比如Hibernate的SessionFactory

    四:实际应用

    JDK中java.lang.Runtime 使用单例模式的饿汉式

      

    有道词典
    public static v ...
    详细X
     
    instance  ['ɪnst(ə)ns]  详细X
    基本翻译
    n. 实例;情况;建议
    vt. 举...为例
    网络释义
    INSTANCE: 实例
    Instance variable: 实例变量
  • 相关阅读:
    C#使用Oracle.ManagedDataAccess.dll
    C#调用webservice
    “认证发布”和“获取展示”,如何在 SharePoint 中正确使用 RSS Feed。
    不怕你配置不会,就怕你看的资料不对!MIM 与 SharePoint 同步完全配置指南。
    SharePoint Server 2013 安装篇
    打印机服务不能正常启动
    JAVA课程体系
    学习网
    Oracle Database 11g安装教程
    方法重载
  • 原文地址:https://www.cnblogs.com/wjh123/p/11095229.html
Copyright © 2020-2023  润新知