延续 Android Singleton 单例模式应用01
在01收尾时我们举了一个需要消耗时间、资源才能初始化Singleton的例子
但通常我们在执行不能立即完成的程式一定会放在Thread中执行,主要是避免画面因为在等待未执行完的程式而卡住
延续01 Singleton的範例 这边直接加上Thread来避免画面卡住的问题
结果却发现一件很恐怖的事情,不是说好了用Singleton只会产生一个物件,怎么还是产生了两组
再回头仔细看一下产生Singleton的判断大概就会发现
sInstance == null 这个判断大概佔不到1毫秒
new ApiRequest(context) 这个动作可能需要超过1秒的执行时间
用一个不是很专业的时间线来说明一下
onCreate中开始跑Thread A后,Activity就结束了onCreate阶段来到onResume
进入后也立即开始Thread B,但是在跑Thread B时Singleton仍未被初始化完成所以也跑了一遍初始化
就导致了虽然用了Singleton机制但仍产生了两组物件的状况
解决问题的方法 synchronized
synchronized分两种方式使用,其一是synchronized method,把某一个方法标示为synchronized,另一种则是synchronized block,是将某个程式区段标示为synchronized,这边我把两种结果都做出来
synchronized method
synchronized block
乍看之下好像两种方式都会获得一样的结果
马上举个反例出来,synchronized block没用好的话Singleton马上就烂掉
当然也并不是说都使用synchronized method就完全没毛病
说明一下这边範例,在getInstance前半段Sleep 3秒,这3秒可替代为任何所有程式,不影响Singleton的产生结果,但会因为synchronized method导致这段计算的程式不能同时被两个Thread使用,而导致在onCreate等待3秒,onResume再等待3秒,总共是6秒的等待时间(这边Log是onCreate及onResume的时间差,所以只有3秒)
马上来优化一下,把synchronized method改成synchronized block,Sleep 3秒的部分,分别在两个Thread同时执行了,所以在onCreate及onResume间几乎没有时间差了
结论是,我认为synchronized method及synchronized block并没有好坏之分,开发者应该要因应当下的情况选择使用的方式