浅学单例模式总结
Posted 德宝爸爸嘚吧嘚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅学单例模式总结相关的知识,希望对你有一定的参考价值。
在项目开发过程中,有些特殊对象应当避免重复初始化,例如数据库连接。这些对象在JVM中只需初始化一次,在内存中固定分配一部分空间即可。这类对象往往使用单例模式实现初始化。
下面我们来看看例子:
上图中为避免使用者重复new FileIO(),将fileIO设置为静态变量,在调用静态方法的时候初始化一次,达到单例的效果。但如果站在并发编程的角度上看,上图还是存在问题。当两个线程同时调用getInstance方法时,会实例化两次。
所以必须对代码进行改造。
利用synchronized同步锁的机制可以避免上述问题,只有当前线程释放锁后,下一个线程才可以访问getInstance方法获取实例。
仔细考虑这种代码还是存在优化空间,当fileIO不为空时,是不需要获取锁、释放锁的操作的。
通过这种优化后,当fileIO不为空时,直接返回fileIO。为什么要做第二次fileIO的非空判断?因为当FileIO为空时,多线程调用此方法,有可能出现多次实例化的情况。
Volatile的意思为不稳定的,易变的。Java中被volatile修饰的变量,被调用的时候会去主内存(所有线程共享内存)中获取最新的值。
我们假设线程一进入第二次检验之后就执行FileIO fileIO = new FIleIO()操作,在这个操作中,JVM主要干了三件事
1、在堆空间里分配一部分空间;
2、执行FileIO的构造方法进行初始化;
3、把fileIO对象指向在堆空间里分配好的空间。
但是,当我们编译的时候,编译器在生成汇编代码的时候会对流程顺序进行优化。优化的结果是有可能按照1-2-3顺序执行,也可能按照1-3-2顺序执行。
我们知道,执行完3的时候就fileIO对象就已经不为空了,如果是按照1-3-2的顺序执行,恰巧在执行到3的时候(还没执行2),突然跑来了一个线程,进来getInstance()方法之后判断fileIO不为空就返回了fileIO实例。
此时fileIO实例虽不为空,但它还没执行构造方法进行初始化。又恰巧构造方法里面需要对某些参数进行初始化。后来闯进来的线程糊里糊涂对那些需要初始化的参数进行操作就有可能报错奔溃了。”
当然还有最终极:枚举类型。
这是我的第一篇学习笔记,以后会有第二篇第三篇,坚持下去!
以上是关于浅学单例模式总结的主要内容,如果未能解决你的问题,请参考以下文章