• Java设计模式:单例模式


    前言

    以前对设计模式没有太大感觉。现在慢慢在工作中越来越感觉设计模式的重要性,所以决定重头来好好学习整理下常用的设计模式。
    本文介绍的最初级的一个设计模式 单例模式

    模式说明

    java中单例模式定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供。

    应用: 一个系统中多线程对一个文件进行操作,这个文件就需要保证只有一个实例,等等

    饿汉式

    说明:饿汉式意思就是无论系统需不需要使用该类的实例对象,先在类加载的时候创建好
    优点:实现简单
    缺点:容易造成内存的浪费

    常用饿汉式

    该方式是在该类被加载的时候,就创建好了实例化对象。不允许其他地方通过构造方法来创建对象,只能通过提供的指定公共方法来获取唯一的对象。

    public class SingletonDemo1 {
    
        //static 确保在类加载的时候就会初始化该对象
        private final static SingletonDemo1 singleton = new SingletonDemo1();
    
        // 必须是私有构造方法,防止其他地方通过构造方法来实例化对象
        private SingletonDemo1(){
        }
    
        // 是一个公共的静态方法,用于对外提供唯一的对象
        public static SingletonDemo1 getInstance(){
            return singleton;
        }
    
    }
    

    枚举

    根据枚举的特性,可以使用枚举来实现单例模式

    public class SingletonDemo3 {
    
        // 不允许其他地方通过构造方法进行实例化对象
        private SingletonDemo3(){}
    
        //对外提供可获取唯一实例化对象的公共方法
        public static SingletonDemo3 getInstance(){
            return Singleton.SINGLETON.getInstance();
        }
    
        private enum Singleton{
            SINGLETON;
    
            private SingletonDemo3 singleton;
    
            Singleton(){
                singleton = new SingletonDemo3();
            }
    
            public SingletonDemo3 getInstance(){
                return singleton;
            }
        }
    
    }
    

    懒汉式

    说明:懒汉式意思就是在系统第一次需要使用该类的实例对象时,再创建该类的实例对象。
    优点:不造成内存没必要的浪费
    缺点:实现相对较难

    懒汉式-线程不安全

    在有多线程使用的情况下不要使用,否则可能会造成创建多个实例对象。一般建议不使用该种方式。

    public class SingletonDemo1 {
    
        //static 确保在类加载的时候就会初始化该对象
        private static SingletonDemo1 singleton = null;
    
        // 必须是私有构造方法,防止其他地方通过构造方法来实例化对象
        private SingletonDemo1(){
        }
    
        // 是一个公共的静态方法,用于对外提供唯一的对象
        public static SingletonDemo1 getInstance(){
            if(singleton==null){
                singleton = new SingletonDemo1();
            }
            return singleton;
        }
    
    }
    

    懒汉式-线程安全-同步方法

    由于上面的方式,是在执行getInstance()方法时,多线程使用时可能出现创建多个对象的情况。那可以直接将该方法进行同步,保证任意时间,最多是能一个线程使用该方法。

    public class SingletonDemo2 {
    
        //static 确保在类加载的时候就会初始化该对象
        private static SingletonDemo2 singleton = null;
    
        // 必须是私有构造方法,防止其他地方通过构造方法来实例化对象
        private SingletonDemo2(){
        }
    
        // 是一个公共的静态方法,用于对外提供唯一的对象
        public static synchronized  SingletonDemo2 getInstance(){
            if(singleton==null){
                singleton = new SingletonDemo2();
            }
            return singleton;
        }
    
    }
    

    缺点:太重了,每个线程在每次使用的时候,都需要进行同步,而实际上只是在第一次获取该类的实例对象时需要同步,往后使用不需要同步。

    懒汉式-线程安全-双重锁

    该方式只会在未实例化对象时,才同步进行实例化对象。实例化后就不需要再进行同步了。

    public class SingletonDemo2 {
    
        //static 确保在类加载的时候就会初始化该对象
        private static volatile SingletonDemo2 singleton = null;
    
        // 必须是私有构造方法,防止其他地方通过构造方法来实例化对象
        private SingletonDemo2(){
        }
    
        // 是一个公共的静态方法,用于对外提供唯一的对象
        public static SingletonDemo2 getInstance(){
            if(singleton==null){
                synchronized (SingletonDemo2.class){
                    if(singleton==null) { //为了防止多个线程进行实例化
                        singleton = new SingletonDemo2();
                    }
                }
            }
            return singleton;
        }
    
    }
    

    有么有注意到,使用了volatitle关键字,为什么要使用volatile关键字?
    答:这里使用了volatile一个重要的特性——禁止JVM指令重排序
    singleton = new SingletonDemo2()的在jvm内存中会有三步,1)分配内存;2)初始化对象;3)将对象指向分配的内存。jvm在会在不改变最终执行结果的情况下对指令进行重排序,即:可能执行顺序是1->3->2,若是在执行执行3还未执行2时,其他线程执行使用,则会报错。
    (参考:https://www.cnblogs.com/crossoverJie/p/9326788.html)

    参考资料

    https://www.cnblogs.com/paul011/p/8574650.html
    http://www.runoob.com/design-pattern/singleton-pattern.html
    java实例化对象过程说明:https://blog.csdn.net/justloveyou_/article/details/72466416

  • 相关阅读:
    stat函数讲解
    ptrace 人人小站
    调试器工作原理——基础篇
    open和fopen的区别:
    memset ,memcpy 和strcpy 的根本区别?
    log4j日志配置详解
    jvm调优的参数设置
    mysql的密码设置
    java基础类、接口、成员属性的修饰符
    java基础之类(包含内部类)与接口的特点
  • 原文地址:https://www.cnblogs.com/wsygdb/p/9352030.html
Copyright © 2020-2023  润新知