使用单例模式可以减少内存消耗,一般写法如下:
public class Application { private static volatile Application instance; private Application(){ } public static Application getInstance(){ if (instance == null){ synchronized (Application.class){ if (instance == null){ instance = new Application(); } } } return instance; } }
第一个 instance == null 主要是为了解决 有instance的时候直接renturn
第二个 synchronized (Application.class) 主要是了解决线程同步的问题
第三个 instance == null 有可能第一个线程new出来application,但是第二个线程刚得到锁,所以这个地方必须在加一次非空验证。
volatile的作用主要是为了防止指令重排序。
先解释下指令重排序:一般来说,处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的。
为展示此事件的发生情况,假设代码行 instance =new Singleton(); 执行了下列伪代码:
mem = allocate(); //为单例对象分配内存空间. instance = mem; //注意,instance 引用现在是非空,但还未初始化 ctorSingleton(instance); //为单例对象通过instance调用构造函数
当线程1只是给instance设置了一块内存空间时,线程2 instance就不会为空,结果就会返回一个只是有内存空间但是没有调用构造函数的instance
instance =new Singleton(); 的正确的执行流程应该是:
1.先给单例对象分配一块内存空间。
2.在这个内存空间上执行构造函数。
3.将instance引用指向真实地址。