iT邦幫忙

0

Android Singleton 單例模式應用02(Multi-Thread、Synchronize)

延續 Android Singleton 單例模式應用01

在01收尾時我們舉了一個需要消耗時間、資源才能初始化Singleton的例子
但通常我們在執行不能立即完成的程式一定會放在Thread中執行,主要是避免畫面因為在等待未執行完的程式而卡住

延續01 Singleton的範例 這邊直接加上Thread來避免畫面卡住的問題
結果卻發現一件很恐怖的事情,不是說好了用Singleton只會產生一個物件,怎麼還是產生了兩組
https://ithelp.ithome.com.tw/upload/images/20200519/20126774MhRDcfXCax.png

再回頭仔細看一下產生Singleton的判斷大概就會發現
sInstance == null 這個判斷大概佔不到1毫秒
new ApiRequest(context) 這個動作可能需要超過1秒的執行時間
https://ithelp.ithome.com.tw/upload/images/20200519/20126774STNUOA46HW.png

用一個不是很專業的時間線來說明一下
onCreate中開始跑Thread A後,Activity就結束了onCreate階段來到onResume
進入後也立即開始Thread B,但是在跑Thread B時Singleton仍未被初始化完成所以也跑了一遍初始化
就導致了雖然用了Singleton機制但仍產生了兩組物件的狀況
https://ithelp.ithome.com.tw/upload/images/20200519/20126774Cl50cjBeuR.jpg

解決問題的方法 synchronized

synchronized分兩種方式使用,其一是synchronized method,把某一個方法標示為synchronized,另一種則是synchronized block,是將某個程式區段標示為synchronized,這邊我把兩種結果都做出來

synchronized method
https://ithelp.ithome.com.tw/upload/images/20200519/20126774yRoIwLIiBJ.png

synchronized block
https://ithelp.ithome.com.tw/upload/images/20200519/20126774jlR0jJrnH8.png

乍看之下好像兩種方式都會獲得一樣的結果
馬上舉個反例出來,synchronized block沒用好的話Singleton馬上就爛掉
https://ithelp.ithome.com.tw/upload/images/20200519/201267746KjBvDF1ti.png

當然也並不是說都使用synchronized method就完全沒毛病
說明一下這邊範例,在getInstance前半段Sleep 3秒,這3秒可替代為任何所有程式,不影響Singleton的產生結果,但會因為synchronized method導致這段計算的程式不能同時被兩個Thread使用,而導致在onCreate等待3秒,onResume再等待3秒,總共是6秒的等待時間(這邊Log是onCreate及onResume的時間差,所以只有3秒)
https://ithelp.ithome.com.tw/upload/images/20200519/20126774bXXBeTHs6U.png

馬上來優化一下,把synchronized method改成synchronized block,Sleep 3秒的部分,分別在兩個Thread同時執行了,所以在onCreate及onResume間幾乎沒有時間差了
https://ithelp.ithome.com.tw/upload/images/20200519/20126774AyWqyRw9e0.png

結論是,我認為synchronized methodsynchronized block並沒有好壞之分,開發者應該要因應當下的情況選擇使用的方式


尚未有邦友留言

立即登入留言