单例模式

设计模式之单例模式

单例模式:通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的方法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。
--------参考于《大话设计模式》
通俗的来说,单例模式就是让构造器私有化,并且这个类只能有一个实例,还要提供一个方法可以得到这个实例对象。

1:饿汉式

饿汉从字面上来理解就是,见了食物要立马去吃,很积极
通过代码来理解就是,就是你不需要我这个实例,但是我也给你创建好了,如果你要用,那么你直接调用我就可以了
在这里插入图片描述
以上代码,先私有化了自己的构造器,使得外界不能通过new的方式来创建这个类的对象,并且在内部自己提供了提供了一个方法,用来返回自己的实例化对象,由于这个方法使用了static修饰,所以此时当我们要使用这个类中的方法是,可以通过
类名.方法名来获取此类的对象,然后就可以直接使用此类的方法了
在这里插入图片描述
这样的做法相对来说会更安全一些,但是通过反射我们还是能够获取到的。

2:懒汉式

懒汉从字面上来理解就是很烂,个人感觉也可以称作饱汉式
通过代码来理解,就是当你需要我的时候,我才会给你创建对象让你去调用,你不用我,我就不给你创建对象
在这里插入图片描述
以上代码是最简单的懒汉式,但是会存在着一些线程不安全的问题
我们来分析下当线程a进入了if方法时,并没有来的及new出一个对象的时候,b也想进来,并且此时并没有创建出对象,那么b自然而然就可以进来创建对象,此时就相当于有两个线程进入了if方法等待创建对象,故以此推想,若此时有上万个线程都在外准备进入if方法,并且此时还并未创建出Full对象,那么就会有更多的线程进入到if方法中,从而就会创建出更多的Full对象,故造成了线程不安全的问题
在这里插入图片描述
所以我们也解决这个问题,就要保证当一个线程进入到了if方法中,其他的线程就不能进来,只能在外面等待
所以我们可以加一个synchronized用来同步此方法,这样就保证了线程的安全
在这里插入图片描述
上述代码虽然已经解决了线程不安全的问题,但是synchronized的作用域贴在了方法上,性能会降低,故我们要尽量减小synchronized的作用域
在这里插入图片描述
我们只需要将if代码块同步起来就可以了,并且synchronized的同步对象为当前修饰方法所在类的字节码文件,故应为Full.class,此时我们的代码已经比较优雅了,虽然我们不能做到真的完美,但是我们要努力做到趋近于完美
于是我们返现这段代码还是有一些不足,就是当我们的线程每次进入getInstance方法时,线程都要进行同步,这样也会降低性能,我们想要得是,当线程进入getInstance方法时,先不同步,先去判断有没有创建Full对象,如果没有,再去同步代码块,故我们就采用了双重检查加锁
简单的说下双重检查加锁机制:要使用volatile修饰符。双重检查加锁机制就是并不是每次进入synchronized方法都需要同步,而是先不用去同步,先去判断是否创建了实例,如果没有创建则再去下面的代码块,此谓第一重检查:当进入下一块代码块中后,再检查一次是否有实例对象存在,若果没有,此时再去创建对象。此谓二重检查.这样下来,在这个代码块的运行当中synchronized关键字只需要同步一次代码块就可以了,极大地降低了性能的损耗。

以下贴出我们最终的懒汉式代码
在这里插入图片描述
这样就真正解决了线程不安全的问题,
被volatile修饰的变量的值不会被本地线程缓存,对其的操作都是直接操作内存,从而保证多线程正确处理.但是使用volatile关键字会使java虚拟中一些必要的优化失效。
所以还是用饿汉式吧
若有出错,还望指正,共勉

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值