zoukankan      html  css  js  c++  java
  • 《Head First设计模式》 读书笔记06 单件模式 Singleton Pattern

    《Head First设计模式》 读书笔记06 单件模式 Singleton Pattern

     

    单件模式 Singleton Pattern

      类只存在一个实例,即只可以创建一个对象。

      有一些类如果创造出多个对象就会导致许多问题的产生,如程序的行为异常、资源使用过量,或者是不一致的结果。

      单件模式常常被用来管理共享的资源,例如数据库连接或者线程池。

      单件模式的实现是通过private构造函数,类中含有一个静态方法getInstance(),调用这个方法可以创建并返回唯一的对象,也可能返回的是已经创建好的对象。

     

    单件模式的简要定义

      单件模式确保一个类只有一个实例,并提供一个全局访问点。

     

    单件模式的实现

      单件模式,首先要限制从外部创建对象,所以将构造方法声明为私有private,这样就只能在类内部调用构造函数。

      如何调用这个构造函数?要使用这个类,而又没有这个类的对象,所以需要一个静态的方法,这个方法调用私有的构造函数,并且返回唯一的单件对象。

      唯一的对象保存在类内,多次创建时,返回的是同一个对象。

    单件模式实现1

      根据上述内容,一种单件实现方式如下:  

    单件模式 实现1
    //第一种实现,多线程存在问题
    class Singleton
    {
        private static Singleton singleton;
        private Singleton()
        {
        }
    
        public static Singleton getInstance()
        {
            if(singleton == null)
            {
                singleton = new Singleton();
            }
    
            return singleton;
        }
    }

      但是这种实现方式存在问题,在多线程的情况下,可能会创建多个对象。

      怎么解决多线程单件问题呢?下面有三种方法:

    单件模式实现2

      通过synchronized关键字解决多线程问题:  

    单件模式 实现2
    //第二种实现,通过synchronized关键字解决多线程问题
    //synchronized关键字迫使每个线程在进入方法前,要先等候别的线程离开该方法
    //也就是说,不会有两个线程可以同时进入这个方法
    //PS:同步会降低性能
    class Singleton
    {
        //private static Singleton singleton = new Singleton();
        private static Singleton singleton;
        private Singleton()
        {
    
        }
    
        public static synchronized Singleton getInstance()
        {
            if(singleton == null)
            {
                singleton = new Singleton();
            }
    
            return singleton;
        }
    }

      这种方法会造成性能的降低。一旦对象被创建,仍然多次进行同步,是一种累赘。

    单件模式实现3

      使用双重检查加锁(double-checked locking),首先检查实例是否已经创建了,如果尚未创建,才进行同步。这样一来,只有第一次会同步。

    单件模式 实现3
    //第三种实现,利用双重检查加锁
    //在getInstance()中减少使用同步
    //注意:双重检查加锁不适用于java1.4以及之前的版本
    class Singleton
    {
        //Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。
        //即阻止线程为了优化性能而保有变量的私有拷贝
        private volatile static Singleton singleton;
        private Singleton()
        {
    
        }
    
        public static Singleton getInstance()
        {            
            if(singleton == null)//检查实例,如果不存在就进入同步区块
            {
                //注意,只有第一次才彻底执行这里的代码
                synchronized(Singleton.class)
                {
                    if(singleton == null)//进入区块后,再检查一次
                    {
                        singleton = new Singleton();
                    }
                }
            }
    
            return singleton;
        }
    }

    单件模式实现4

      第四种实现是将对象的创建提前完成,用时返回,也被称为“急切”创建实例的方法。 

    单件模式 实现4
    //第四种实现,将实例化操作提前
    //在静态初始化的时候创建单件,保证线程安全
    class Singleton
    {
        private static Singleton singleton = new Singleton();
        private Singleton()
        {
    
        }
    
        public static Singleton getInstance()
        {
            return singleton;
        }
    }

     

    其他相关问题

      类加载器class loader可能会导致单件失效。

  • 相关阅读:
    c++关键字static的作用
    react 中echarts-for-react使用 自适应div
    react Echart 自适应问题
    react 中Echarts不自适应问题
    解决 react typescript 中 antD 走马灯 this.slider 报错
    antD 走马灯跳到指定页面
    js 判断语句 或的写法
    ajax 分页点击数据缓存
    react antD moment
    react antD 日期选择
  • 原文地址:https://www.cnblogs.com/mengdd/p/2853687.html
Copyright © 2011-2022 走看看