单例模式:默认情况下,由spring管理的对象都是单例的!
####懒加载:
默认情况下,由spring管理的对象如果是单例的,会是饿汉式的,即加载Spring的配置文件时,就会初始化需要管理的对象!
##目标
某个类只能被获取到1个实例(对象),在这个实例没有被销毁之前,不可以创建出新的实例。
- 所有正在执行的程序和数据必须存放在内存中。
- new对象表示像JVM申请新的内存空间,用于存放即将创建的对象的数据。
为了避免可以随意创建对象:
单例模式--饿汉式 对象已经创建好,后面想用可以直接调用,称之为饿汉式
单例模式--懒汉式
如果懒汉式的单例代码写的不严谨,可能出现线程的安全问题!
> 如果程序使用了多线程,可以表现为多个线程是“同时”运行的。
> 使用sychronized实现“互斥锁“,锁的对象对于多个线程来说必须是同一个对象!
### 实现
但是上述方法使用this来锁对象, 是不可行的,因为static方法,是不属于对象的,在类加载时就已经存在了,那么此时的this无法成立。所以引入了其他方式:
这种方式引用的字符串对象,是可以锁同一个对象的!!
但是锁字符串形式在工作当中并不是规范写法,默认的会创建个对象来锁住!!
引用了一个取钱的案例:
此时运行出来的结果就出现了问题,两个线程在if判断的过程当中都执行了操作,引发了问题。
要解决以上问题,让取钱正常,需要对线程加锁!
同时,上述的测试方法是直接用thread.start()方法来启动的
之前说过,对于线程安全问题,采用互斥锁可以解决,但是锁的对象不同,很显然互斥锁写的有问题,那么接着改进!
对比之前的内容,发现改进的并不大,只是将锁的this改成了字符串常量,那么这样一来也做到了锁同一个对象。
有的人不适应这种写法,想仍然采用this来锁对象,那么我们的代码就得进一步改进了。
1.首先改变线程的创建方式: 实现Runnable接口。
注:此处的锁,锁住的this,如果是锁住了同一个对象,那么我们同样可以采用锁方法的形式,锁方法在此刻与锁this是一样的效果。
2.线程只关乎Thread,采用Runnable接口,可以重写run方法,但是和线程没有关系,所以我们在测试过程中,需要改进测试案例,以Thread来启动。
此时得到的结果,就得看你手动传入的对象,如果相同,this指代的同一对象,否则仍然有问题。
总结:
两种方式的单例模式,其实无所谓孰优孰劣,工作当中,喜欢使用哪个便使用哪个,因为没有明确的机制要引用哪一种方法!