`
zenghuiss
  • 浏览: 26585 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

"多余"的单例模式

    博客分类:
  • Java
阅读更多
最近正在看设计模式,发现一点小东西,分享一下~
先上代码
class A{
  private static A a = null;
  private A(){}
  public static A getInstance(){
    if(a==null){
      a = new A();
    }
    return a;
  }
}

这个相信大家都很熟悉,一眼就能看到问题之所在,这段代码的本意是在整个JVM中创建一个A的实例,所以才会有if(a==null)的检查,但在多线程的情况下了?想象一下有2个Thread,简称t1,t2好了,假设t1比t2先进入这段
1)t1进入if判断,并开始准备执行new A(),此时a还是null
2)t2这时候也进来了,a==null是true,所以t2不可避免的也new了一个
问题就出现了,t1、t2它们各自独立的拥有一个A的实例,没有达到单例的效果

为了克服这个问题,我们稍微改下
class A{
  private static A a = null;
  private A(){}
  public static synchronized A getInstance(){
    if(a==null){
      a = new A();
    }
    return a;
  }
}

现在问题解决了,因为加了synchronized关键字

但再想,这个同步锁只需在A第一次实例化的时候起作用,但以后每次都会要去同步,反成了提升性能的瓶颈了,所以聪明的人想出了下面的优化策略;
class A{
  private static A a = null;
  private Date date = new Date();
  private A(){}
  public Date getDate(){
    return date;
  }
  public static A getInstance(){
    if(a==null){//1
      //2
      synchronized(A.class){
        //3
        if(a==null){//4
          a = new A();
        }
      }
    }
    return a;
  }
}

这样小小的改动后,我们再分析一下
还是t1,t2
1)t1先到达1处,条件满足a==null,
2)t1到达2,并得到锁,到达3处
3)t1new出了一个A的实例,这时t2进来发现a!=null,所以直接return a
并调用a.getDate();
4)t1调用a.getDate();
A类的变量初始化和变量date的赋值顺序的不可预料性,如果一个线程在没有同步化的条件下去读取a的引用,并调用它的方法,可能会发现date对象的初始化还未完成,进而造成崩溃。
上面这种做法其实在C里面是很常见的,叫双重检查(Double Check),而在java中就不行了,就是因为java编译时的顺序不可预见性,所以一定要多注意.
分享到:
评论

相关推荐

    原生javascript单例模式的应用实例分析

    在软件设计模式中,单例模式属于创建型模式的一种,它能够确保一个类只有一个实例,并提供一个全局访问点。JavaScript作为一种灵活的编程语言,虽然没有类和实例的概念,但借助函数和闭包,同样可以实现单例模式。 ...

    scala设计模式

    例如,Scala中的case classes和case objects能够很自然地实现单例模式,而无需额外的工厂模式来创建对象实例。 文章重点介绍了几种经典的设计模式以及在Scala中的实现方式: 1. 工厂方法模式:这种模式通过将对象...

    JavaScript面向对象的程序设计(犯迷糊的小羊)

    在JavaScript中,单例模式通常通过立即执行的函数表达式(IIFE)来创建。 5. 工厂模式 工厂模式是创建对象的一种方法,它可以根据输入创建不同类型的对象。工厂模式隐藏了对象的创建逻辑,从而使得使用该模式的代码...

    【C#基础】单实例例子

    Public保证了它的全局可见性,静态方法保证了不会创建出多余的实例。 2)将类的构造函数设为Private,即将构造函数"隐藏"起来,任何企图使用构造函数创建实例的方法都将报错。这样就阻止了开发人员绕过上面的...

    struts2面试题1.pdf

    Struts1 Action 是单例模式,并且必须是线程安全的,因为仅有 Action 的一个实例来处理所有的请求。单例策略限制了 Struts1 Action 能作的事,并且要在开发时特别小心。Action 资源必须是线程安全的或同步的。在 ...

    数据库,宾馆管理系统

    - 设计模式:如工厂模式用于创建数据库连接,单例模式管理全局资源,策略模式处理不同类型的折扣策略等。 - MVC(Model-View-Controller)架构:分离业务逻辑、视图展示和用户交互,提高代码可读性和可维护性。 - ...

    C++面试题以及基本答案

    - **项目中的应用**: 在实际项目中,设计模式可以帮助解决特定问题,如单例模式用于确保类只有一个实例,并提供一个全局访问点;工厂模式用于创建对象的接口,但让子类决定实例化哪一个类。 #### 7. 设计模式的理解...

    java面试题

    10. **设计模式**:作为解决常见问题的最佳实践,设计模式在面试中常常被提及,如单例模式、工厂模式、装饰器模式、观察者模式等。 通过深入学习和练习"Java面试题",尤其是"SCJP认证试题解析"中的题目,不仅可以...

    Structs1.x与Structs2.0的区别

    Structs1.x的Action是单例模式,并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Structs1.x Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。 ...

    C#代码风格指南

    3. **设计模式**:根据项目需求,合理使用设计模式,如工厂模式、观察者模式、单例模式等。 **代码示例** 1. 提供代码示例以说明上述规则的应用,确保示例代码清晰易懂,遵循相同的风格指南。 总之,C#编码风格...

    Sr.Develop infomation

    13. **设计模式**:设计模式如工厂模式、单例模式、观察者模式、装饰器模式等,需要绘制UML图展示其实现。 14. **JavaScript面向对象**:JavaScript中的类和继承可以通过构造函数和原型链实现,例如创建水果和苹果...

    google-java-styleguide

    3. 单例模式:推荐使用静态工厂方法代替公有构造函数实现单例。 四、异常处理 1. 异常类型:尽量避免使用`Exception`作为抛出的异常类型,应具体到某种异常,如`IOException`。 2. try-catch-finally:`finally`块...

    2024年java面试题-tomcat面试题

    - **单例模式**:每个Servlet类只有一个实例,在整个应用生命周期中复用。 - **懒加载**:只有在第一次请求时才会创建Servlet实例,节省资源。 #### 其他配置选项 - **maxHttpHeaderSize**: HTTP请求头信息的...

    struts2开发指南

    - Struts1.x的Action类是单例模式,所有请求共享一个实例,可能导致线程安全问题,需要开发者确保Action资源的线程安全性。 - 在Struts2中,每个请求都会创建新的Action实例,解决了线程安全问题,同时也更易于...

    java泛型源码-JavaToJson-JsonToJava:将Java转换为Json或将Json转换为Java的通用源代码

    10. **代码设计模式**:项目可能采用了工厂模式、单例模式或策略模式等设计模式来提高代码的可扩展性和复用性。 总的来说,这个项目是一个利用Java泛型技术实现的JSON转换工具,它提供了一种通用的方式来在Java对象...

    面试题目.docx

    - **单例模式**:理解单例模式的设计思想和实现方式。 ### 24. 项目和技术框架 - **项目经验**:详细介绍自己参与过的项目背景、技术选型、遇到的问题及解决方案。 - **技术框架**:熟悉常用的Java框架(如Spring、...

    2020年最新阿里开发手册1.6.0(泰山版).zip

    12. **设计模式**:推荐使用常见的设计模式,如单例、工厂、观察者等,以提高代码的复用性和扩展性。 以上仅是手册中部分关键知识点的概述,实际的手册中包含了更深入的讨论和详细的示例,涵盖了从基本的编码习惯到...

    java编码规范_new .rar

    10. **设计模式**:理解并应用常见的设计模式,如单例、工厂、观察者等,以实现可扩展和可维护的代码。 11. **单元测试**:编写测试用例以验证代码功能,使用JUnit或其他测试框架进行自动化测试。 12. **代码格式...

    Java范例开发大全 (源程序)

     实例156 Singleton单例模式 242  实例157 招聘(简单工厂模式) 243  实例158 同学聚会(工厂方法模式) 244  实例159 图书展(抽象工厂模式) 246  实例160 汽车适配器(Adapter适配器模式) 248  8.4 ...

Global site tag (gtag.js) - Google Analytics