美文网首页
设计模式思考之单件模式

设计模式思考之单件模式

作者: lhsjohn | 来源:发表于2019-03-03 22:41 被阅读0次

    单件模式的定义

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

    类图

    单件模式.jpg

    1.其中uniqueInstance 变量持有唯一的单间实例

    2.getInstance()方法是静态的,这意味着它是一个类方法,所以可以在代码的任何地方使用Singleton.getnstance()访问它。这样和访问全局变量一样,只是多了一个优点:单件可以延迟实例化。

    3.单件模式的类也可以是一般的类,具有一般的数据和方法。

    下面是一个单件模式的经典实现:

    Public class Singleton(){
    //利用一个静态变量来记录Singleton类的唯一实例
    Private static Singleton uniqueInstance;
    //这里是用到的其他的有用的实例化的变量
    
    //把构造器类设置为私有的,只有自Singleton类内才可以调用构造器
    Private Singleton() { }
     
    //用getInstance()方法实例化对象,并返回这个对象的实例
     Public static Singleton getInstance(){
        If(uniqueInstance==null) {  
           uniqueInstance=new Singleton();
     }
         Return uniqueInstance;
     
    }
    
    //这里是其他有用的方法
    
    }
    

    单件模式的多线程之伤

    现在我们知道,绝大多数的应用程序都是多线程的,那么我们如果采用上面经典的单例模式的实现化,遇到多线程情况,就会遇到很大的麻烦了

    下面我们来处理这种麻烦,处理多线程

    在这里只需要我们把getInstance() 变成同步(synchronized)方法即可。

    
    Public class Singleton(){
    //利用一个静态变量来记录Singleton类的唯一实例
     Private static Singleton uniqueInstance;
    //这里是用到的其他的有用的实例化的变量
    
     //把构造器类设置为私有的,只有自Singleton类内才可以调用构造器
    Private Singleton() { }
     
    //用getInstance()方法实例化对象,并返回这个对象的实例
    Public static synchronized Singleton getInstance(){
        if(uniqueInstance==null) {  
         uniqueInstance=new Singleton();
    }
       Return uniqueInstance;
     
     }
    
    //这里是其他有用的方法
    
    }
    
    
    

    通过增加synchronized 关键字到getInstance()方法中,我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。

    但这里需要我们注意的是,尽管用这个方式可以很简单的解决了上面的问题,但是这种方法却会降低应用程序的性能。

    所以我们考虑一下,能否改善多线程呢?

    下面是我们可以采取的几种选择:

    1.如果getInstance()的性能对于应用程序不是很关键,就什么也不用去做,直接可以采取上面所说的加上 synchronized 的做法。

    2.使用”急切”创建实例,而不用延迟实例化的方法

     Public class Singleton{
     //在静态初始化器中创建单件,这段代码保证了线程安全。
    Private static Singleton uniqueInstace= new     Singleton();
      
    Private Singleton () {}
    
    Public static Singleton getInstance() {
            Return uniqueInstance;
         }
    
     }
    
    
    

    采用这个做法,我们依赖JVM 在加载这个类时马上创建此唯一的单件实例。JVM保证在任何线程访问uniqueInstance静态变量之前,一定会创建此实例。

    3.用“双重检查加锁”,在getInstance()中减少同步
    利用双重检查加锁,首先检查是否实例已经创建了,如果尚未创建,”才”进行同步,这样一来,只有第一次会同步,这正是我们想要的。

    
     Public class Singleton{
     //在静态初始化器中创建单件,这段代码保证了线程安全。
    Private static Singleton uniqueInstace;
      
    Private Singleton () {}
    
    Public static Singleton getInstance() {
     If(uniqueInstance ==null){
       Synchronized(Singleton.class) {
        If(uniqueInstance ==null){
         uniqueInstance =new Singleton();
       }
      }
     }
        Return uniqueInstance;
     }
    }
    
    

    注意如果使用的是JVM1.2或之前的版本,我们必须建立单间注册表,以免垃圾回收器将单件回收。

    总的来说,单件模式相对于其他模式来说类图结构虽然没有那么复杂,但它却扮演着非常重要的角色,在保证应用程序的稳定性和安全性方面起着非常重要的作用。

    作者:lhsjohn

    相关文章

      网友评论

          本文标题:设计模式思考之单件模式

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