2022年1月23日 星期日

[Geroge]設計模式-單例模式(下)

單例模式進階

單例模式線程安全問題(最主要問題)

    餓漢式 hungry

    優點: 線程安全

    缺點: 過早浪費資源


    懶漢式 lazy

    優點: 使用時才創建, 資源節約

    缺點: 為線程安全要付出額外代價

解決線程安全的懶漢式單例模式:

    1 synchronized方法

    2 雙重檢測鎖單例模式

    3 內部類Holder式(建議使用)

例子:

問題點: 我們有一個懶漢式的單例模式, 我們讓他在創建的時候睡3秒鐘, 而執行的時候其中一個開執行續執行, 另外再執行創建一次, 我們會發現不同執行續下, 他就會創建出兩個物件




















要解決這個問題, 我們可以在getInstance上面加上synchronized關鍵字, 這樣就可以達到同步















然而, 同步是相當消耗資源, 這會導致說, 如果我們系統有很多地方要去getInstance的話, 它的效率就會很低, 為了提出解決效率的問題, 我們就有了"雙重檢測鎖機制"

他的意思是, 如果判斷為空, 我就去加鎖, 保證後面這段部分只有一個人執行, 相當於說, 兩個線程不能同時進到加鎖內的程式碼區塊, 這時特別注意要加入volatile才能保證他正常執行, 他的意思是對於後面的變量"SingleTonDoubleCheck"不會被改變他的執行順序, 因為new SingleTonDoubleCheck() 他有可能不是一個原子操作, 可能是先產生singleTon, 然後分配空間, 才new, 這樣兩到三個動作中, 因此是有可能他還沒有執行完整new動作, 另一個線程就近來判斷為null, 反而再產生了一個新物件, 這也產生一個問題, 就是volatile效率也是相對較低的, 每次都透過內存器去真正取值, 而沒有透過暫存器去緩存, 另外, 他有一個鎖的話, 始終還是會帶來效率問題的












那最佳的解法, 是由內部類Holder來創建Singleton, 他是由內部類中, 由內部類來放靜態的實例, 然後再getInstance中, 才去返回instance, 首先這個new SingleTinHolder這件事, 他是直接在類加載的時候來創建, 就克服了線程安全的問題, 因為它是由靜態內部類來做, 也就是它是由java內部來完成, 因此他是保證單線程訪問, 那他也結合懶漢式的優點, 是在我們使用到getInstance方法的時候才去加載, 所以不會過早創建而浪費資源











https://www.youtube.com/watch?v=w-BlQ5tsZfU&list=PLGmd9-PCMLhb16ZxeSy00qUsBazXgJyfM&index=11

https://github.com/iw5420/geroge-design-pattern

沒有留言:

張貼留言

創業想法1

現在有駐點工作的公司 今天突然想到 那為什麼沒有遠端駐點公司 就是接國外的職位 幫他找台灣人 在公司上遠端工作的職缺 有可能是因為時差 所以這種公司上班時間不同, 並不好管理 但是感覺理論上是存在需求 就是台灣人想找遠端職缺, 但是可能語言上或技能上還差點火候 公司提供培訓, 並...