多线程与单例模式
笔记原本记录在有道或者印象笔记上,为了方便,现将部分笔记摘抄至随笔,以供日后参考。
有些自己总结的部分内容可能不太正确,希望发现的人可以为我指出,谢谢!
本部分内容取自《JAVA多线程编程核心技术》(高红岩著)第六章:多线程与单例模式,在此基础上进行了精简及解释,特此说明。
饿汉模式(立即加载):急迫、急切地初始化。在使用类的时候已经将对象创建完毕。类内部直接初始化
懒汉模式(延迟加载):不急切地初始化,在需要时才进行初始化(getInstance内部判断是否为空后进行初始化)
通过synchronized关键字进行加锁:十分耗时,效率低下
解决方案:
解决方案1:DCL(Double-Check Locking).
两次都check是否为空,instance需要使用volatile,需要Jdk5以上。
双重检查加锁:volatile关键字,getInstance内部还是使用synchronized。
可以在第一个if进入之后执行一些业务处理及准备工作
使用volatile关键字:保证第二个判断非空时的instance是最新的值
解决方式2:静态内置类(内部类) 在初始化时jvm保证了只会初始一个实例
解决方式3:通过static静态代码块实现单例,此处不做具体说明
解决方式4:枚举类型在使用时会自动调用构造方法,和静态代码块类似。
枚举及其枚举变量在jvm只会存在一个。注意枚举类型不要暴露在外部,避免违反职责单一的原则
关于枚举类型为什么可以实现单例可参见:https://blog.csdn.net/Insert_day/article/details/70832185
注意:在单例对象序列化与反序列之后不能保证单例(写入后读出破坏了单例),在单例反序列时需要使用readResolve方法代替readObject,该方法依旧返回instance。jvm会自动执行readResolve方法保证单例