单例模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。

---恢复内容开始---

1.优缺点

  单利模式就是在一个jvm中只能存在一个实例(不考虑反射)这样设计主要有两方面好处:

    1.从jvm来说,对于频繁使用的对象,可以减去创建的时间(这对于重量级的对象,是非常客观的开销),由于new 对象的操作减少,对系统内存的使用频率降低,将会减轻GC压力,缩短GC停顿时间(摘自 java程序性能优化 --葛一鸣)。

    2.从设计来讲,某些实例一个系统中本应只存在一个(逻辑上),并且只对同一对象操作,能有效的保证一致性(并发时可相应处理)。

  同时也存在一些需要注意的问题:   

    1、由于单利模式中没有抽象层,不利于扩展,所以很多责任都是自己扛,可能会导致单例类的职责过重,在一定程度上违背了“单一职责原则”。

    2.如这个实例创建过程很慢而且不一定会用到,可能需要延迟加载。

    3、滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。

2.实现方式

  实现单例的根本是私有化构造器(在类内部创建对象),然后根据不同的场景设计获取实例的方法,下面是几种常见的实现方式。

    1.饿汉式: 这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。 基于类加载机制实现可避免多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到延迟加载的效果。  

技术分享
 1 /**
 2  * 饿汉式
 3  */
 4 public class Singleton {
 5     private static Singleton instance = new Singleton();
 6     private Singleton (){}
 7     public static Singleton getInstance() {
 8         return instance;
 9     }
10 }
View Code

    2.懒汉式:可实现延迟加载,但是多线程下存在致命问题。

技术分享
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}
View Code

    3.改进的懒汉式(为解决线程同步问题),最简单的方法是对getInstance方法整体加关键字synchronized,但是这种实现方式效率会至少低2个数量级。其中一种不错的改进方式是双重检查模式(DCL),这种写法在getSingleton方法中对singleton进行了两次判空,第一次是为了不必要的同步,第二次是在singleton等于null的情况下才创建实例。在这里用到了volatile关键字,在这里使用volatile会或多或少的影响性能,但考虑到程序的正确性,牺牲这点性能还是值得的。DCL优点是资源利用率高,第一次执行getInstance时单例对象才被实例化,效率高。缺点是第一次加载时反应稍慢一些,在高并发环境下也有一定的缺陷(DCL失效),虽然发生的概率很小。

技术分享
 1 public class Singleton {  
 2       private volatile static Singleton singleton;  
 3       private Singleton (){
 4       }   
 5       public static Singleton getInstance() {  
 6       if (instance== null) {  
 7           synchronized (Singleton.class) {  
 8           if (instance== null) {  
 9               instance= new Singleton();  
10           }  
11          }  
12      }  
13      return singleton;  
14      }  
15  } 
View Code

    4.静态内部类:既可以实现延迟加载,又不会有线程问题(推荐

 

 

  

 

以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章

常用代码片段

性能比较好的单例写法

片段作为 Android 中的单例

单例片段或保存网页视图状态

你熟悉的设计模式都有哪些?写出单例模式的实现代码

单例模式以及静态代码块