首页
学习
活动
专区
工具
TVP
发布

Java单例模式之饿汉式、懒汉式及双重判断加锁深入讲解

前言

在Java设计模式中,单例模式是最为简单而且使用频率也是很频繁的一种设计模式,在以后的Spring学习过程中,就会发现,在Spring中的Bean默认也就是单例的。所谓单例,也就是说这个类的实例对象只能有一个,如何达到这一点呢?那么本文主要学习单例模式的设计。

单例模式

设计思路:

单例类只能有一个实例。

单例类的构造方法设计为私有的,目的在于外部不能去创建。

既然外部不能去实例化,那么就必须在本类中自己去创建实例对象,并且必须设计为private私有的。

外部如果要去访问这个类的实例对象,那么这个单例类必须内部提供一个方法供外部去访问。

单例类可以设计为final的,这样这个单例类也不允许被子类继承。

方式一:饿汉式

优点:设计简单,不存在多线程安全问题。

缺点:当Singleton类被加载的时候,静态代码就会被初始化,那么就意味会去创建实例对象并且分配内存空间,那么之后呢,不管这个实例对象用不用,都会占据内存空间。当我们将一个很大的对象通过饿汉式的方式去设计的时候,显然是不太合适的。

方式二:懒汉式

优点:设计也是比较简单的,和饿汉式不同,当这个Singleton被加载的时候,被static修饰的静态变量将会被初始化为null,这个时候并不会占用内存,而是当第一次调用getInstance方法的时候才会被初始化实例对象,很显然,这种方式是按需创建。

缺点:在单线程环境下是没有问题的,在多线程环境下,会产生线程安全问题。

问题:如何解决懒汉式在多线程环境下的多实例问题?

方式一:使用同步方法解决

优点:方便。

缺点:每次调用getInstance方法都会线程同步,效率十分低下,而且当创建好实例对象之后,也就不必继续进行同步了。

方式二:同步代码块(双重判断加锁定)

优点:不是很好理解,为什么说使用这种方式就可以解决多线程问题呢?实际上我们可以这样理解,首先添加了一个同步代码块,在同步代码块中去判断实例对象是否存在,如果不存在则去创建,这个时候其实就完全可以解决问题了,因为虽然是多个线程去获取实例对象,但是在同一个时间也只会有一个线程会进入到同步代码块,那么这个时候创建好对象之后,其他线程即便再次进入同步代码块,由于已经创建好了实例对象,便直接返回即可。但是为什么还要在同步代码块的上一步再次去判断single为空呢?这个是由于当我们创建好实例对象之后,直接去判断此实例对象是否为空,如果不为空,则直接返回就好了,就避免再次进去同步代码块了,提高了效率。

缺点:无。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190828A0R74200?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券