美文网首页
11.1设计模式-单例模式-详解

11.1设计模式-单例模式-详解

作者: 205蚁 | 来源:发表于2018-11-18 17:12 被阅读0次

    单例模式:

      1. 单例介绍
      1. 单例的六种写法和各自特点
        饿汉、懒汉、懒汉安全、DCL、静态内部类、枚举。
      1. android中的单例
        application实例、
        单例引起的内存泄露,EventBus异步实现库所造成的内存泄露以及解决办法

    1.单例介绍

    1.概念
        单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以保证系统中一个类只产生一个实例。
        java里头,单例概念是在虚拟机的范围内,装载类是在虚拟机中,ClassLoader装载实现单例类的时候,就会创建一个类的实例
    2.好处
        1.对于频繁使用的对象,可以省略创建对象所花费的时间,它对于那些重量级对象而言,是非常可观的一笔系统开销
        2.由于new 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间
        
    写法:
        1.私有静态对象
        2.私有的构造方法
        3.公共的静态的获取单例对象入口方法getInstance()
    

    2.单例的六种写法和各自特点

    饿汉、懒汉、懒汉线程安全、DCL、静态内部类、枚举。
    饿汉:图。               
    无法对单例对象创建做延时加载。只要使用了这个类。比如类的静态方法,单例对象就会被创建,因为有static的成员变量
    懒汉:图。 多线程中无法保证实例唯一,这样的实现是失效的
    懒汉线程安全:
        图。1.在getInstance方法外使用 synchronized
         2.或者在方法内部锁住class
        性能效率不足
    
    DCL:双检查所机制:
        public class DclSingleton{
            private static DclSingleton mInstance = null;
            private DclSingleton();
            public static DclSingleton getInstance(){
                //避免不需要的同步
                if(mInstance == null){
                    synchronized(DclSingleton.class){
                        //在第一次调用时初始化
                        if(mIntance == null){
                            mInstance = new DclSingleton();//有改进的地方
                        }
                    }
                }
                return mInstance;
            }
        }
    

    解决了 性能、线程安全问题。
    待改进地方:mInstance = new DclSingleton();不是原子操作
    JVM :1.分配内存 2.调用 构造方法初始化变量 3.将创建的对象指向我们分配的内存空间
    JVM存在指令排序的优化,以上三个步骤可能不是依次执行的,而是乱序-->线程不安全

    修改 private static volatile DclSingleton mInstance =null;//可见性
    保证线程在本地不会存有mInstance的副本,每次都去内存中读取。更重要的原因是禁止JVM重排序的优化,也就是原有三步一定依次执行,不存在重排序的情况
    
    解决了线程安全问题,也存在JVM的即时编译器中存在指令重排序的优化,禁止后缺少该优化
    优化:静态内部类/枚举
    1.主要原因。JVM提供的同步控制。 static 、final。 static进行区块的初始化数据,保证我们的数据在内存中是同一份。
    final 字段初始化之后无法被修改
    图:
        public class StaticInnerSingleton{
            private StaticInnerSingleton(){
            }
            public static StaticInnerSingleton getInstance(){
                return SingletonHolder.sInstance;
            }
            //静态内部类 里头创建对象实例
            ;只要没有使用这个内部类,JVM就不会加载这个类,也就不会创建里面的单例对象。从而这里就完成了懒汉式的延时加载 。static又完成了线程安全
            只有在调用了getInstance之后,java的虚拟机才会加载SingleHolder,并实例化instance
            妙处:利用了类中静态变量的唯一性,同时JVM加载机制保证了线程安全,同时我们没有使用关键字同步,保证了性能 3.SingleHolder是私有的,外部无法使用,保证了安全
            private static class SingletonHolder{
                private static final StaticInnerSingleton mInstance = new StaticInnerSingleton();
            }
            
        }
    

    3.android中的单例

    application实例、
    单例引起的内存泄露,EventBus异步实现库所造成的内存泄露以及解决办法
    

    相关文章

      网友评论

          本文标题:11.1设计模式-单例模式-详解

          本文链接:https://www.haomeiwen.com/subject/wspgfqtx.html