单例设计模式进阶
最近研究项目底层使用依赖组件的源码,发现了单例模式的正确使用姿势,同时重温《Java程序性能优化》章节的讲解,两相印证对单例设计模式算是整明白了。
单例模式:设计目的是对于频繁使用的对象,单例可以节省创建对象花费的时间。
常说的饿汉式,懒汉式,只是形象化的比喻,方便去理解设计模式,结果本末倒置,只记住了名词,忘记了名词代表的背后含义。
通过两两比较,来剖析单例不同模式的优缺点:
懒汉式比较于饿汉式核心的意义在于引入懒加载,在需要使用的时候才创建对象,而不是系统启动的时候就创建
优点1:避免系统启动时有额外的负载
优点2:单例类可能有其他的方法,饿汉式的方式会导致只要使用这个单例类的地方都会初始化这个单例变量(这点往往被忽视,导致无法认识懒加载的优点)
饿汉式 懒汉式在使用懒汉式的时候,有人会说已经添加了volatile关键字,为什么还需要添加synchronized关键字,其实是对于volatile关键字理解不正确导致的,volatile并不能保证多线程的安全性,只能保证修饰变量的可见性和有序性,所以在多线程场景下,如果不加synchronized关键字,线程1正在创建对象,线程2判断instance为null,也新建了一个单例对象,就有多个实例被创建,到了这里,出现了一个我一直纠结的问题,多个实例都一样,能咋地,也没啥影响哇,直到看到了举例:win系统只有一个回收站,为什么,因为如果在一个窗口中删除的文件在另一窗口还存在,有歧义,全局唯一在这个例子中体现的很明确,解释的很合理,说服了我。
但是为了使用懒加载而引入的同步关键字,又带来了另一个缺点,系统性能的损耗,所以引出了工作中项目使用的更好的创建方式,使用静态内部类:
内部类实现静态内部类的加载时机:
外部类加载的时候,内部类不会被初始化
调用静态内部类的变量时,外部类也不会加载,避免了引入同步关键字,具备饿汉式和懒汉式各自的优点,真的很优秀。