zoukankan      html  css  js  c++  java
  • 【转】单例模式

    单例定义: 

         单例是指在一个JVM实例中,只存在一个对应Class的实例对象。 

    单例可以分为状态化和无状态化使用方式,比如网站的访问次数计数器,这个是有状态的实现,单态能够保存这个计数,并且使用同步或原子变量实现计数。另外,单例也可以无状态使用,提供工具性质的工作。使用单例模式的直接好处就是限制了实例个数,节省内存资源,有利于Java垃圾回收。 

    如何使用单例模式? 

    目前单例模式支持如下三种实现: 

    1. 饿汉模式: 

    Java代码  收藏代码
    1. public class Singleton1 {  
    2.       
    3.     private static final Singleton1 INSTANCE = new Singleton1();  
    4.       
    5.     private Singleton1() {}  
    6.       
    7.     public static Singleton1 getInstance() {  
    8.         return INSTANCE;  
    9.     }  
    10. }  





          饿汉模式形象的描述了单列实例化的时间点,也就是在Class对象完成加载后就直接创建了该单列对象,而不是在第一次使用的时候才创建。这一点原理类似于Spring的BeanFactory和ApplicationContext类在创建Bean对象时候的区别,前者是第一次使用的时候创建bean,后者是在Spring容器启动时创建好了所有bean,这两种创建方式各有优势,但目前大部分应用主要采用的是第二种实现方式。 

    2. 饱汉模式: 


    (1) 使用同步关键字 

    Java代码  收藏代码
    1. public class Singleton3 {  
    2.       
    3.     private static Singleton3 INSTANCE;  
    4.       
    5.     private Singleton3() {}  
    6.       
    7.     public static synchronized Singleton3 getInSingleton() {  
    8.         if (INSTANCE == null) {  
    9.             INSTANCE = new Singleton3();  
    10.         }  
    11.         return INSTANCE;  
    12.     }  
    13. }  





    (2) DCL方式 

    Java代码  收藏代码
    1. public class Singleton2 {  
    2.       
    3.     private volatile static Singleton2 INSTANCE;  
    4.       
    5.     private Singleton2() {}  
    6.       
    7.     //DCL  
    8.     public static Singleton2 getInstance() {  
    9.         if (INSTANCE == null) {//--------(1)  
    10.             synchronized (Singleton2.class){//----------(2)  
    11.                 if (INSTANCE == null) {  
    12.                         INSTANCE = new Singleton2();//-------------(3)  
    13.             }  
    14.             }  
    15.         }  
    16.         return INSTANCE;  
    17.     }  
    18. }  





         饱汉模式的实现是单例模式中最容易出错,也是问题最多的一种实现方式,我们常见的DCL(双锁检查机制),就是这种方式提出来衍生出来的问题。 

    在双锁检查机制中,很多开发者,或者说很多已经在生产环境运行的程序可能都存在着一定的问题,虽然这些小问题发生的几率极小,但是理论上是存在的,在此处,我们来详细讨论这个问题。双锁检查对机制中属性没有加volatile关键字,可能存在错误。 

           • 外部获得一个没有被初始化完成的对象 

          很多从事Java开发的程序员可能只知道Volatile关键字保证了多线程的可见性,而还有一种特性就是:保证该关键字修饰的对象被初始化完成。我们来假设一个前提,假设Singleton2对象的初始化需要做很多工作,需要很长的时间才能完成。在程序运行,由于JMM对程序运行多了优化,可是使一个对象获得没有被初始化完成的引用,所以很有肯能导致外部对象获得一个没有初始化完成的Singleton2的应用,即便这种情况的发生的几率十分小,但是理论上还是存在,我们需要理解到这一点,以便我们编写出高质量的代码。 

    3. 延迟加载模式 

         延迟加载模式也许这种叫法不是很标准,姑且这样称呼。在该模式下,使用一个内部类来实例化外部的单态对象,这样做的优势是,即满足了延迟加载的思想,提高代码的运行效率,而且又保证了对象创建的安全性。所以该模式是比较值得推荐的一种单态模式实现。具体代码如下: 

    Java代码  收藏代码
      1. public class Singleton4 {  
      2.       
      3.     private static class SingletonHolder {  
      4.         public static final Singleton4 INSTANCE = new Singleton4();  
      5.     }  
      6.       
      7.     private Singleton4() {}  
      8.       
      9.     public static Singleton4 getInstance() {  
      10.         return SingletonHolder.INSTANCE;  
      11.     }  
      12. }  
  • 相关阅读:
    第二个冲刺 6.3.4.学术诚信与职业道德
    第二个冲刺 Sprint
    css之清除浮动
    style和getComputedStyle(ff)和currentStyle
    php 中间件
    Vue 和 angular
    img 分区响应图
    PHP composer
    php实现文件上传,下载的常见文件配置
    php 命名空间
  • 原文地址:https://www.cnblogs.com/iusmile/p/2679568.html
Copyright © 2011-2022 走看看