zoukankan      html  css  js  c++  java
  • 创建型模式之单例模式

    一、介绍

    类的单例设计模式,就是采用一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。

    二、单例模式八种方式

    1. 饿汉式(静态常量)
    2. 饿汉式(静态代码块)
    3. 懒汉式(线程不安全)
    4. 懒汉式(线程安全,同步方法)
    5. 懒汉式(线程安全,同步代码块)
    6. 双重检查
    7. 静态内部类
    8. 枚举

    1、饿汉式(静态常量)

    class Singleton{
    
    //    1.构造器私有化,外部不能new
        private Singleton(){}
    
    //    2.本类内部创建对象实例
        private final static Singleton instance = new Singleton();
    
    //    3.提供一个共有的静态方法,返回实例对象
        public static Singleton getInstance(){
            return instance;
        }
    }
    

    优缺点:

    1. 优点:方法简单,在类装载的时候就完成实例化,避免线程同步。
    2. 缺点:没有达到 Lazy Loading 的效果。如果从始至终没有使用这个实例,则造成内存浪费。
    3. 结论:可用,但可能造成内存浪费。

    2、饿汉式(静态代码块)

    class Singleton{
        
    //    1.构造器私有化,外部不能new
        private Singleton(){}
        
    //    2.本类内部创建对象实例
        private static Singleton instance;
        
        static { // 静态代码块中创建单例对象
            instance = new Singleton();
        }
        
    //    3.提供一个公有的静态方法,返回实例对象
        public static Singleton getInstance(){
            return instance;
        }
    }
    

    优缺点:

    1. 方法和第一种类似,只不过将类实例化的过程放在了静态代码块中。优缺点和第一种方式一样。
    2. 结论:可用,但可能造成内存浪费。

    3、懒汉式(线程不安全)

    class Singleton{
        private static Singleton instance;
    
        private Singleton(){}
    
    //    提供一个静态的公有方法,当使用到该方法时,才去创建 instance
    //    即懒汉式
        public static Singleton getInstance(){
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    优缺点:

    1. 优点:起到了 Lazy Loading 的效果,但只能在单线程下使用。
    2. 缺点:如果在多线程下,一个线程进入了 if(instance == null) 判断语句中,没执行完,另一个线程也通过了这个判断语句,这时就产生了多个实例。
    3. 结论:在实际开发中,不要使用这种方式。

    4、懒汉式(线程安全,同步方法)

    class Singleton{
        private static Singleton instance;
    
        private Singleton(){}
    
    //    提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
        public static synchronized Singleton getInstance(){
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    优缺点:

    1. 优点:解决了线程安全问题。
    2. 缺点:效率太低了。每个线程想获得类的实例都要执行 getInstance() 方法同步,只有第一次实例化才要用到同步锁,后面的要获得该类的实例,直接 return 就行了。
    3. 结论:在实际开发中,不推荐使用这种方式。

    5、懒汉式(线程安全,同步代码块)

    class Singleton{
        private static Singleton instance;
    
        private Singleton(){}
    
        public static Singleton getInstance(){
            if(instance == null){
                
                synchronized (Singleton.class){
                    instance = new Singleton();
                }
            }
            return instance;
        }
    }
    

    优缺点:

    1. 本质跟上一种方法一样。
    2. 结论:不推荐使用。

    6、双重检查

    class Singleton{
        private static volatile Singleton instance;
    
        private Singleton(){}
    
    //    提供一个静态的公有方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题
    //    同时保证了效率,推荐使用
        public static Singleton getInstance(){
            if(instance == null){
                synchronized(Singleton.class){
                    if(instance == null){
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    优缺点:

    1. 优点:Double-Check 概念是多线程开发中常使用的。延迟加载,效率较高。
    2. 结论:在实际开发中,推荐使用这种单例设计模式。

    7、静态内部类

    class Singleton{
    
        private Singleton(){}
    
    //    写一个静态内部类,该类中有一个静态属性
        private static class SingletonInstance{
            private static final Singleton INSTANCE = new Singleton();
        }
    
    //    提供一个静态的公有方法,直接返回 SingletonInstance.INSTANCE
        public static synchronized Singleton getInstance(){
            return SingletonInstance.INSTANCE;
        }
    }
    

    优缺点:

    1. 原理:这种方式采用了类装载的机制来保证初始化实例时只有一个线程。静态内部类方式在 Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance 方法,才会装载 SingletonInstance 类,从而完成 Singleton 的实例化。类的静态属性只会在第一次加载类的时候实例化,所以在这里,JVM帮助我们保证了线程的安全,在类进行初始化时,别的线程是无法进入的。
    2. 优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。
    3. 结论:推荐使用。

    8、枚举

    //使用枚举,可以实现单例,推荐
    enum Singleton{
        INSTANCE; //属性
    
    //    public void sayOK(){
    //        System.out.println("ok~");
    //    }
    }
    

    优缺点:

    1. 借助JDK1.5 中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建对象。
    2. 结论:推荐使用。

    三、单例模式在 JDK 应用的源码分析

    1. JDK中,java.lang.Runtime 就是经典的单例模式(饿汉式)
    2. 代码:

    四、单例模式注意事项和细节说明

    1. 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要创建销毁的对象,使用单例模式可以提高系统性能。
    2. 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new。
    3. 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)。
  • 相关阅读:
    new JSONObject()报空指针异常
    转:修改Fckeditor 2.6 增加插入Mp3等多媒体文件功能
    执行更新操作时,timestamp类型的字段自动被更新为了系统当前日期
    读取某个文件的位置
    myeclipse配置注释
    为eclipse 的 hibernate 配置文件加提示
    hibernate3与hibernate4
    查看eclipse版本
    Eclipse编译没有class文件生成
    严重: Error loading WebappClassLoader context:
  • 原文地址:https://www.cnblogs.com/xiaoran991/p/12490039.html
Copyright © 2011-2022 走看看