单例模式 分析代码优化方法_java

单例模式是23种设计模式之一,是比较简单的一种设计模式,它的目的是无论调用多少次,都返回同一个对象,它的特点是构造器私有化。

  它分为两种结构,一种是懒汉式的,一种是饿汉式的,它们各有优缺点,我们先从饿汉式看起,代码如下:

public class Single {
  private static Single single = new Single();
  private Single() {
  }
   public Single getInstance() {
    return single;
  }
}

通过上面的程序可以看出来虽然我们加载同一个对象的目的确实达到了,但当程序被加载的时候就会创建single这个对象,当这个类有多个这样的方法时,我们可能会用不到这个对象中大多数单例,就会造成对内存的浪费。所以就出现了懒汉式的单例模式,代码如下:

public class Single {
  private static Single single = null;
  private Single() {
  } 

  public Single getInstance() {
    if(single==null){
      single = new Single();
    }
    return single;
  }
}

这样,只有当我们真正调用这个对象时它才会被new出来,但是这样是存在问题的。

  当上面的第二段代码在第一次加载的时候有两个线程对其进行了调用,则会产生两个不同的对象,所以是线程不安全的,这时候就会想到给这个方法加个锁,加锁之后的代码如下:

public class Single {
  private static Single single = null;
  private Single() {
  } 

  public synchronized Single getInstance() {
    if (single == null) {
      single = new Single();
    }
    return single;
  }
}

这样做确实做到了线程安全,但是当加锁这个方法里面要执行很多东西,调用这个方法花费的时间会很长,这样对服务器来说是致命的,因为这个方法如果某个线程一直调用的话,其它的线程是没有办法调的,服务器就阻塞了,那么升级后的代码如下:

public class Single {
  priate static Single single = null;
  private Single() {
  } 

  public Single getInstance() {
    if (single == null) {
      synchronized (Single.class) {
        single = new Single();
      }
    }
    return single;
  }
}

仔细观察以后发现这样并没有锁住,当第一次同时有两个线程到达getInstance()方法if判断时,其中有一个肯定是阻塞的,当另外一个执行完以后,阻塞这个线程是不会再判断是否为空的,还是会创建一个对象的,这样又有多个对象被产生了,再对其进行升级,得到的代码如下:

public class Single {
  private static Single single = null;
  private Single() {
  } 

  public Single getInstance() {
    if (single == null) {
      synchronized (Single.class) {
        if (single == null) {
          single = new Single();
        }
      }
    }
    return single;
  }
}

这样就不会产生上面的问题,而且也只锁一次,因为第二次再执行这个方法时,会跳过if判断,直接返回single,不会再被锁,执行效率也会很高。

  但即使是这样,也还是有问题的,因为我们不能确定在内存中是先给对象赋值,还是先创建了这个对象,所以第二个程序有可能得到的是初始化一半了的对象,在jdk1.5之后,我们可以用volatile这个关键字来避免这种情况,代码如下:

public class Single {
  private static volatile Single single = null;
  private Single() {
  } 

  public Single getInstance() {
    if (single == null) {
      synchronized (Single.class) {
        if (single == null) {
          single = new Single();
        }
      }
    }
    return single;
  }
}

但是这种情况很少使用,我在这里只是为了学习一下,嘻嘻

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索单例模式
java单例模式代码、单例模式优化、java单例模式、java单例模式例子、java单例模式的作用,以便于您获取更多的相关知识。

时间: 2024-09-20 14:20:22

单例模式 分析代码优化方法_java的相关文章

sql千万级数据分页效率分析与方法

sql千万级数据分页效率分析与方法 select top 100 * from (select top 500 * from T1 order by id asc) a order by id desc 先asc取前500条 再倒着取(desc)这个结果的100条... MSSQL在我这里测试通过 这个ID字段如果是默认的升序序列 也是主键列 那下面这句就能实现了 select * from t1 where id between 400 and 500 我就知道三种方法 having in  

Tomcat内存溢出分析及解决方法_java

JVM管理两种类型的内存,堆和非堆.堆是给开发人员用的上面说的就是,是在JVM启动时创建:非堆是留给JVM自己用的,用来存放类的信息的.它和堆不同,运行期内GC不会释放空间. 一.内存溢出类型 1.java.lang.OutOfMemoryError: PermGen space JVM管理两种类型的内存,堆和非堆.堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的.它和堆不同,运行期内GC不会释放空间.如果web app用了大量的第三方jar或者

网站数据收集、整理、分析的方法和技巧

中介交易 SEO诊断 淘宝客 云主机 技术大厅 任务要求: 2010年10月18日中午12:00,入门任务第二期的任务开始,任务如下,对当前网络下的所有链接平台进行数据的收集整理和分析. 任务目的: 这次任务主要是锻炼我们的是几个力:执行力,耐力,分析能力,吃苦能力,这个是考验一个人工作是不是有耐心,会不会去动脑做事情,在收集的过程中,总是复制,粘贴这些枯燥无味并且重复性的工作,也是对一个人体力和眼力的考验.这个工作在第一个任务中也有对这方面的考验. 收集平台和整理平台可以说是另外一个力:苦力,

盘点关键词竞争度分析新方法

网站SEO优化核心工作之一是关键词的选择.我们在选择关键词的时候会考虑一些因素.但是现在随着搜索引擎的算法不断改变,将排名的权利逐渐向用户倾斜.也就是在网站排名里面越来越多的加入了用户体验的因素.导致现在就算是新站也有可能会战胜老站.今天就来介绍一些新方法进行关键词竞争度分析. 我们常见的关键词竞争度分析考虑的因素有:百度指数,搜索量,看排序中竞价网站的个数,自然排名中网站首页的个数,自然排名前十网站的质量,百度推广后台服务等等.在考虑这些因素的时候,我们会对关键词的热门程度做一个统计.分析出关

解析Java程序中对象内存的分配和控制的基本方法_java

一.对象与内存控制的知识点 1.java变量的初始化过程,包括局部变量,成员变量(实例变量和类变量). 2.继承关系中,当使用的对象引用变量编译时类型和运行时类型不同时,访问该对象的属性和方法是有区别的. 3.final修饰符特性. 二.java变量的划分与初始化过程 java程序的变量大体可以分为成员变量和局部变量,成员变量可以分为实例变量(非静态变量)和类变量(静态变量),一般我们遇到的局部变量会在下列几种情况中出现: (1)形参:在方法签名中定义的局部变量,由调用方为其赋值,随着方法结束消

七种角度分析对应分析方法

对应分析方法与对应图解读方法--七种分析角度     对应分析是一种多元统计分析技术,主要分析定性数据Category Data方法,也是强有力的数据图示化技术,当然也是强有力的市场研究分析技术.     这里主要介绍大家了解对应分析的基本方法,如何帮助探索数据,分析列联表和卡方的独立性检验,如何解释对应图,当然大家也可以看到如何用SPSS操作对应分析和对数据格式的要求!     对应分析是一种数据分析技术,它能够帮助我们研究由定性变量构成的交互汇总表来揭示变量间的联系.交互表的信息以图形的方式

Java利用反射自动封装成实体对象的方法_java

本文实例讲述了Java利用反射自动封装成实体对象的方法.分享给大家供大家参考.具体分析如下: 利用此方法的时候需要传递的参数的名称,必须以行号结尾,去掉行号就是属性名称,比如页面传递name+rowNo,那么实体对象的属性名应该为name.代码如下 复制代码 代码如下: //获取页面数据,自动封装成bean对象 public List getObjectList(Class clazz,String[] rowNos) throws Exception{         List objList

java读取properties配置文件的方法_java

本文实例讲述了java读取properties配置文件的方法.分享给大家供大家参考.具体分析如下: 这两天做java项目,用到属性文件,到网上查资料,好半天也没有找到一个满意的方法能让我读取到.properties文件中属性值,很是郁闷,网上讲的获取属性值大概有以下方法,以下三种方法逐渐优化,以达到最好的效果以下都以date.properties文件为例,该文件放在src目录下,文件内容为: startdate=2011-02-07 totalweek=25 方法一: public class

浅谈产品竞争分析的方法

在企业中竞品分析工作大多数产品经理实际工作中很少去做,要么由市场和运营人员代劳,也或者产品部门配备市场研究相关岗位定期来做.而近来部门同事实行每月对现有产品进行竞品分析,参与一部分工作.对于既不是专才和通才的产品经理来说也是一种全新历练和学习.竞品分析结果只能作为一种参考依据(由于信息挖掘渠道和关注点都相对带有主观性,比较危险的是有些产品经理会特意朝预期潜意识心里判断来收集数据),通常服务于领导及产品管理层对产品信息动态能够有意识的去关注及时调整相关目标: 为什么要做竞品分析? 1.  为企业制