`

JDP-01-[单例模式]-多种实现

 
阅读更多

1. 定义: 单例模式就是确保一个类中只有一个实例,并且该实例必须自动创建,并向整个系统提供该实例。

2. 使用时机: 当系统要求一个类只有一个实例时,就需要使用用单例模式。

 

单例模式是作为对象的创建模式,有三个特点:
1)该类只有一个实例
2)该类自行创建该实例(在该类内部创建自身的实例对象)
3)向整个系统公开这个实例接口

class Singleton {  
  
    //私有,静态的类自身实例  
    private static Singleton instance = new Singleton();  
      
    //私有的构造子(构造器,构造函数,构造方法)  
    private Singleton(){}  
      
    //公开,静态的方法  
    public static Singleton getInstance() {  
        return instance;  
    }  
}

 

这个单例类在自身被加载时instance会被实例化,即便加载器是静态的。因此,对于资源密集,配置开销较大的单体更合理的做法是将实例化(new)推迟到使用它的时候。即惰性加载(Lazy loading),它常用于那些必须加载大量数据的单体。修改下:

class LazySingleton {  
    //初始为null,暂不实例化  
    private static LazySingleton instance = null;  
      
    //私有的构造子(构造器,构造函数,构造方法)  
    private LazySingleton(){}  
      
    //公开,静态的工厂方法,需要使用时才去创建该单体  
    public static LazySingleton getInstance() {  
        if( instance == null ) {  
            instance = new LazySingleton();  
        }  
        return instance;  
    }     
} 

 

class LazySingleton {  
    //初始为null,暂不实例化  
    private static LazySingleton instance = null;  
      
    //私有的构造子(构造器,构造函数,构造方法)  
    private LazySingleton(){}  
      
    //公开,静态的工厂方法,需要使用时才去创建该单体  
    public static synchronized LazySingleton getInstance() {  
        if( instance == null ) {  
            instance = new LazySingleton();  
        }  
        return instance;  
    }     
} 

 

不过这种简单的写法不适合用于像服务器这种服务很多线程的程序上,同步机制会造成相当的效能低落,为了顾及 Singleton Lazy Initialization 与效能问题,因而有了 Double-check Locking 的模式:

 

double-checked locking

 

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

 

也就是只有在第一次建立实例时才会进入同步区,之后由于实例已建立,也就不用进入同步区进行锁定。

 

 问题:Double checked lock也还是不能保证线程安全的。在多核机或者某些jvm实现上,由于指令乱序执行的可能性,还是有可能导致生成多个实例。。。

 

另一种实现方式

 

    class Singleton{  
        class SingletonHolder{  
           private static Singleton instance = new Singleton()  
        }  
        private Singleton(){}  
        public static Singleton getInstance(){  
            return SingletonHolder.instance;  
        }  
    }  

 

public class Singleton {  
  
    private static Singleton instance = null;  
  
    public static Singleton getInstance() {  
        if(instance == null) {  
            instance = SingletonLazy.lazy;  
        }  
        return instance;  
    }  
  
    private static class SingletonLazy {  
        public static Singleton lazy = new Singleton();  
    }  
  
} 
 

classloader首先会加载Singleton.class文件,运行到if(instance==null)这句的时候,如果为空,回去加载SingletoneLazy.class。如此便实现了lazy初始化。

 

枚举实现:

 

package com.flyingh.test3;  
  
public enum Singleton {  
    singleton;  
} 

 

Java Runtime 类别的作法简单的多, 它舍弃了 Lazy Initialization ,如果您要取得单例的机会不是很多,可以用这种方式:

 

    package org.bestupon.dp.singleton;  
    /** 
    *  
    * @author BestUpon 
    * @email bestupon@foxmail.com 
    * @date 2010-6-13上午11:08:28 
    * @ask jdk中Runtime这个类似就是一个单例模式的应用: 
    *  
    * @answer 
    */  
    public class Test4RunTime {  
      
    public static void main(String[] args) {  
    Runtime runtime = Runtime.getRuntime();  
    runtime.freeMemory();  
    }  
    }  

 

    public class Runtime {   
        private static Runtime currentRuntime = new Runtime();   
        public static Runtime getRuntime() {   
            return currentRuntime;   
        }   
       /** Don't let anyone else instantiate this class */   
       private Runtime() {}   
        // 以下略   
    }  

 

Singleton 本身的观念简单但应用 很广,因而很多时候必须对实际环境作一些考虑与调整。

 

总结:

 

单例模式可以分为两种:饿汉式和懒汉式两种,饿汉是在系统启动的一开始就初始化好了实例,而懒汉式是在第一次访问的时候才初始化实例。

HungerSingleton & LazySingleton

优点:

在单利模式中,客户调用类的实例时,只能调用一个公共的接口,这就为整个开发团队提供了共享的概念

缺点:

单利模式在实例化后,是不允许类的继承的;在分布式系统中,当系统的单利模式类被复制运行在多个虚拟机下时,在每一个虚拟机下都会创建一个实例对象,此时如果想知道具体哪个虚拟机下运行着单例对象是很困难的,而且单例类是很难实现序列化的。

疑问:

1)好像单例的特性都可以通过类的静态方法和静态属性实现,为什么还要有单例模式呢?

2)

由于端午节放假的缘故,各位同仁在期间提出了很多的问题,也指出了我思维的局限性,没有及时的更新于回复各位好友的,深表遗憾!


针对单例模式的很多用法,前面一直是在所单一线程的问题,本来设计多线程的问题就很少,也对双重锁定这个问题没有深入的五挖掘,导致了犯了今天这样的错误。 之后参考了一些资料,针对各位朋友提出的问题与我自身存在的问题,进行改进! 参考的文章是:IBMDeveloperWorks(中国)的网站上的文章 双重检查锁定及单例模式 http://www.ibm.com/developerworks/cn/java/j-dcl.html )。这篇文章真针对各种问题都有分析,包括可见性等问题。得出了一个结论:双重锁定失效的主要原因是:不同JVM之间的无序写入问题,多线程之间的独占、休眠(记忆复苏)所引起的不同 不问题。

最终本文提出了一个建议: 议不要使用“双重锁定”! 一个解决单例模式的方案:

底线就是:无论以何 种形式,都不应使用双重检查锁定,因为您不能保证它在任何 JVM 实现上都能顺利运行。JSR-133 是有关内存模型寻址问题的,尽管如此,新的内存模型也不会支持双重检查锁定。

 

未完待续。。。

 

分享到:
评论

相关推荐

    明华汉澳DP-R123-U-SB2(X3-HZ) RD及DP串口系列读写器演示程序及开发包.zip

    适用于RD-EB、RD-ET、RD-EZ、RD-EB-MX、RD-ET-MX、RD-EZ-MX、KRD-EB、KRD-ET、KRD-EZ、KRD-EB-MX、KRD-ET-MX、KRD-EZ-MX 、SRD-R100、Q3-R100、Q3-R101、Q3-R102、DP-R103、DP-R 113、DP-R123、DP-R133、DP-R143、...

    DP-301U网络打印服务器驱动

    DP-301U作为D-LINK的一款产品,支持多种网络协议,如TCP/IP、DHCP、DNS和PPPoE,确保了在各种网络环境下的兼容性。 DP-301U的驱动程序是确保其正常运行的关键软件组件。驱动程序是计算机硬件与操作系统之间的桥梁,...

    DP-302打印服务器1.02版

    DP-302的USB接口打印服务器为用户提供在局域网内分享他们的打印机的服务,并对于那些DP-302兼容的打印机产品提供在线打印服务。DP-302打印服务器允许多个用户直接从电脑上发送文件传输到打印机上进行打印工作。在...

    天际航图像快速建模系统DP-Modeler2.3

    《天际航图像快速建模系统DP-Modeler2.3》是一款专为3D建模和视觉效果设计的专业软件,结合了先进的图像处理技术和高效的工作流程,旨在为用户提供便捷、精准的三维模型构建能力。DP-Modeler是天际航公司的明星产品...

    D-Link DP-302 打印服务器驱动

    总的来说,D-Link DP-302打印服务器驱动是实现高效网络打印的关键组件,它的正确安装和维护对于任何依赖网络打印的组织或个人都是必不可少的。通过了解和掌握这些知识点,用户可以更好地管理和优化他们的打印环境。

    qsh-030-01-x-d-a;qsh-040-01-x-d-dp-a;qte-040-04-xxx-d-a

    qsh-030-01-x-d-a;qsh-040-01-x-d-dp-a;qte-040-04-xxx-d-a;qte-040-xx-x-d-a (1);qth-030-01-x-d-a-l;qth-030-01-xx-d-a;qth-030-01-xx-d-a封装PCB,官方下载

    dp-8016p-pk 32位驱动

    《松下DP-8016P/PK 32位驱动详解及安装指南》 在信息技术领域,打印机是日常办公不可或缺的设备之一。松下DP-8016P和DP-8020P作为高效能的商务打印机,为用户提供了高质量的文档输出服务。然而,为了让这些设备正常...

    DP-301U_UTILITY_PSADMIN_1.00

    DP-301U是一个实用的解决方案,尤其适用于小型办公室或家庭办公环境,它通过USB接口连接打印机,支持多种类型的打印机,确保了广泛的兼容性。 描述中提到,这个驱动程序是由D-Link官方提供的,这确保了其可靠性和...

    DP-301U 共享USB打印服务器配置

    **DP-301U**是一款由D-Link推出的紧凑型打印服务器,专为实现网络共享打印而设计。它通过高速USB端口连接USB打印机,使得局域网内的任何计算机都能方便地访问该打印机。 - **特点**: - 紧凑型设计,节省空间; -...

    DP-ModelerV2.3 用户手册

    ### DP-ModelerV2.3 用户手册知识点详解 #### 1. 系统简介 **1.1 产品概述** DP-ModelerV2.3是一款由武汉天际航信息科技股份有限公司研发的图像快速建模系统。该系统主要用于通过二维图像数据构建高质量的三维...

    D-link DP-302打印服务器software

    综上所述,D-Link DP-302打印服务器软件是实现高效网络打印的关键,它为用户提供了方便、可靠的打印解决方案,是中小型企业或家庭办公环境中提升打印效率的理想选择。正确安装和使用这款软件,可以充分发挥D-Link DP...

    DP-504 DP-508步进驱动器用户手册.pdf

    根据提供的文档内容,DP-504和DP-508步进驱动器是信捷科技电子有限公司生产的产品,它们主要具备以下知识点: 产品概述: DP-504/DP-508步进驱动器是一类细分型步进驱动器,适用于各种中小型自动化设备和仪器。这些...

    DP-DP-Koppler_Rel3_www.44dpdp.com_www.44dpdp.con_EC1-DEB-DPM_GSD

    标题"DP-DP-Koppler_Rel3_www.44dpdp.com_www.44dpdp.con_EC1-DEB-DPM_GSD"中提到的"DP-DP-Koppler"可能指的是一个特定的软件或系统开发项目,其中"DP"可能是项目代号或者代表“Data Processing”的缩写,而"Koppler...

    DP-means k - means聚类算法的比较

    而DP-means的实现可能需要额外的库,如`dpmeans`,这是一个专门为DP-means算法编写的Python包。在给定的项目"Python-DP-Means-Clustering-master"中,很可能包含了这两个算法的代码实现,包括数据预处理、模型训练和...

    DP-100文档.pdf

    DP-100文档是Microsoft Azure认证考试中的一个重要组件,旨在考察考生的数据科学解决方案设计和实现能力。本文档涵盖了DP-100考试的部分内容,涉及到数据科学解决方案的设计、实现和部署等方面。 从题目中,我们...

    D-Link DP-302 V1.03 打印服务器固件

    D-Link DP-302 打印服务器固件,最新V1.03版本。也是最终版本,支持更多打印机。

    DP-851绝版资料

    这表明DP-851不仅仅是一个独立的单板计算机,它还能够与PC协同工作,实现数据的远程监控和采集。这种通信功能在当时是非常先进的技术,它不仅能够提升生产效率,也为故障诊断和远程控制提供了可能。这个特性在现今的...

    DP-301U_v2.36 固件

    DP-301U是一款多功能的打印机服务器,它能够连接多种打印机,并通过网络实现打印共享,方便多个用户同时使用。这个固件版本v2.36的推出,可能包含了多项性能优化和错误修复,旨在提升设备的兼容性、稳定性和安全性。...

    PROFIBUS通讯适配器RPBA-01手册.pdf

    ### PROFIBUS通讯适配器RPBA-01手册知识点概览 #### 一、概述与安全须知 - **标题**: "PROFIBUS通讯适配器RPBA-01手册.pdf" - **描述**: 此文档为ABB RPBA-01 PROFIBUS DP适配器的手册,详细介绍了该适配器的功能...

Global site tag (gtag.js) - Google Analytics