单例模式就是写代码的固定套路,就像高中时语文老师总结出来的主观题的模板,按模板写分数不会太低。所以单例模式写出来的代码不会太差。
单例:一个类,只创建一个实例,不能new多次。单例模式会运用java的语法来让我们只能实例化一次。
本博客主要讨论java中的两种单例模式:饿汉模式和懒汉模式。
以大学生的学习方式为例:饿汉模式相当于在大学里认认真真上好每一节课,无论这些课有没有用都认真学,有的科目要考试直接去考。懒汉模式:相当于在一些同学在上大学时天天逃课打游戏,只有在考试的前几个星期努力的学要考试的几门课,不考试的压根就不学。饿汉模式相当于提前准备好一切。懒汉模式相当于现用现准备。
在计算机领域中,推崇懒汉模式,因为现用先准备的方法极大的提高了效率,以读取文件为例:如果读取的文件很大,饿汉模式要在打开前读取相当长的时间,而懒汉模式只读取用户要阅读的部分,读取时间相对较短。
饿汉模式代码:

由于instance是static修饰的,所以该对象是整个类的,s1,s2在调用的时候都是在调用同一的instance,又由于构造方法是private修饰的,所以无法在该列之外构造,所以s3的构造是错误的。只能使用该类里面的instance。
懒汉模式代码:

只有在第一次使用getInstance时才创建对象。

线程安全问题:
饿汉模式是提前创建好了对象,调用方法只是读操作。
懒汉模式在多线程条件下会出现创建多个对象的现象例如:
![]()
![]()


在这种条件下就会出现创建了两个对象。
解决方法:1.加锁;要保证判断instance是否为空和创建一个新的对象是一个原子操作。

但是加锁也降低了代码的效率,只有第一次执行会触发多创建对象的问题,er第二次执行就不会触发该问题。进行如下修改就可以解决:

最上面的判断是判断是否有必要加锁,若有对象为空就执行加锁及内部内容,若没必要就跳过。
但是这种情况还会出现指令重排序问题在进行new对象时有,3个过程1.分配内存空间,2.调用构造方法,3.把内存地址,付给引用。
假设有2个线程:A和B,A先执行1,3;B开始执行,发现instance已经不为空了,于是跳过new操作,但是instance的初始化并不完整,进行后续的操作时,就会出现Bug。解决方法是:在private static SingletonLazy instance=null;前加上volatile。

被折叠的 条评论
为什么被折叠?



