美文网首页
The Singleton Pattern

The Singleton Pattern

作者: 想跳舞的兔子 | 来源:发表于2019-02-11 19:06 被阅读0次

    本篇我们要讲的是单例模式(the Singleton Pattern)
    单例模式是旨在创造只被创建一次的对象。

    1.模式起源:

    首先,让我们探讨以下,该模式是在何种需求下产生的。
    当我们需要调用对象时,我们通常会创建一个来使用,但是,对于那些共享的变量,我们不能随意创建,因为多例会使本身应该只有一份的对象变成多份,弄乱程序,我们需要做的努力是,如何获取调用一个对象,且该对象只被创建一次。

    2.模式代码进阶:

    首先,我们只对于单线程进行思考。
    1.不能被随意创建的对象意味着我们需要把public的构造器变成private。
    2.因为只有静态类变量/函数可以在不初始化类的条件下依旧可以被调用,所以,我们需要static
    3.为了被私有构造函数创建的单个对象被引用,我们需要定义一个static 的类变量,一个调用对象的static类函数.
    综上,我们可以得出第一个singleton pattern

    public class Singleton{
          private static Singleton uniqueInstance;
          //other useful instance variables here
          private Singleton(){}
          public static Singleton getInstance(){
                if (uniqueInstance == null)
                {  uniqueInstance = new Singleton();}
                return uniqueInstance;
          }
          //other useful methods here
    }
    

    当上例纯粹单线程的时候是没有问题的,但是如果在多线程环境,上述代码会出问题。假设,我们有两个线程同时进行到if (uniqueInstance == null) 且当前uniqueInstance确实为null,那么这两个线程会分别创建一个对象,这就会出问题了。为了修正多线程下的这个问题,我们引入synchronized.

    public class Singleton{
          private static Singleton uniqueInstance;
          //other useful instance variables here
          private Singleton(){}
          public static synchronized Singleton getInstance(){
                if(uniqueInstance == null)
                { uniqueInstance = new Singleton();}
                return uniqueInstance;
          }
    }
    

    引入动态synchronized的代价比较大,我们从下面几个方面来改进多线程:

    • 如果getInstance()的性能并不是至关重要的,那么采用synchronized即直观又有效。但是当getInstance的性能很重要的时候,你需要重新考虑
    • 如果单例变量并不是特别占用空间和时间,而且在程序中一定会创建,那么,我们可以提前创建好,这样避免了多线程可能的重复创建。
    public class Singleton{
          private static Singleton uniqueInstance = new Singleton();
          private Singleton(){}
          public static Singleton getInstance()
          {  return uniqueInstance;}
    }
    

    +我们也可以采用“double-checked locking”来替换synchronized在getInstance()中的使用。

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

    注意:该“double-checked locking”在java版本低于1.4上是不好用的。在JVM上有其他方式来保证同步性,如果你使用JVM而不是java5的话,需要采用其他方式来处理。

    相关文章

      网友评论

          本文标题:The Singleton Pattern

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