設計模式 單例模式的分析與選擇

2021-08-21 05:07:44 字數 1808 閱讀 5146

單例模式:不能自由構造物件、在應用中只存在乙個例項的情況。

例如:載入器中一般都含有這麼幾個部分:requestmanager(請求管理器)、執行緒池、engine(資料獲取引擎)、memorycache、disklrucache、transformation(處理)、target等模組,很消耗資源,沒有必要也不應該建立多個例項。

寫法有多種,下面分析常用的懶漢單例模式的優缺點,並做出最優選擇。

**:

public class singleton1 

public static synchronized singleton1 getinstance()

return sinstance;

}}

* 優點:第一次呼叫getinstance()時才初始化,synchronized保證執行緒安全

* 缺點:每次呼叫getinstance()時都會同步,即使sinstance已經初始化過了,造成不必要同步開銷

**:

public class singleton2 

public static singleton2 getinstance() }}

return sinstance;

}}

getinstance()方法進行了兩次判空,第一次是為了避免不必要的同步,第二次則是在null的情況下建立例項。

看起來很好但是存在問題:因為sinstance = new singleton2()這句不是原子操作(可能會被打斷),它可分為3步:

給sinstance分配記憶體

呼叫建構函式初始化成員變數

將sinstance指向分配的記憶體空間(執行完本操作後,sinstance != null)

假設:執行緒a執行到sinstance = new singleton2()這步,走的順序為1->3->2,當執行完3後,執行緒b直接取走了非空的sinstance(但並沒有初始化),使用時就會出錯,導致dcl(double check lock)失效

* 優點:懶載入,第一次執行getinstance()時單例物件才會例項化,資源利用率高、效率高;

* 缺點:高併發時有風險(小概率發生錯誤);第一次載入稍慢

**:

public class singleton3 

public static singleton3 getinstance() }}

return sinstance;

}}

在dcl基礎上,將sinstance設為volatile

volatile:1.保證執行緒本地不會有變數副本,每次都從主記憶體中讀取;2.保證變數的寫操作都先行發生在後面對於它的讀操作

* 優點:每次都從主記憶體中讀取sinstance,將dcl中sinstance = new singleton2()操作原子化,避免錯誤

* 缺點:多少影響一點效能

* 結論:可以選擇

**:

public class singleton4 

private static class holder

public static singleton4 getinstance()

}

* 優點:懶載入、執行緒安全、保證單例物件的唯一性(靜態內部類只會被載入一次)

* 缺點:無

* 結論:最佳選擇

**:

public enum singleton5
* 優點:寫法簡單

最佳選擇:  4. 靜態內部類單例

第二選擇:2. dcl

第三選擇:3. dcl改善

(個人看法)

設計模式與單例模式

1.是在大量的事件中總結和理論化之後優選的 結構,程式設計風格 以及解決問題的思考方式。2.經典的設計模式有23種 1.採取一定的方法保證在整個軟體系統中,對某個類只能存在乙個物件例項 2.餓漢式 class bank 2.內部建立當前類的例項 private static bank bank ne...

粗糙分析設計模式 單例模式

一山不容二虎,哎 這次就粗糙講解一下單例模式,單例模式是為了讓系統中存在乙個例項,避免同時存在兩個例項下命令,試想一下,如果軟體同時向印表機傳遞命令,那麼印表機不就亂了嘛 臥槽,我該聽誰的 所以,單例模式的存在是非常有必要的,同時,還能減少系統的開銷,如果例項乙個類開銷非常大,單例模式也是非常實用的...

設計模式之單例模式分析

單例模式分為兩大類 懶漢式和餓漢式 其最主要的區別在於 懶漢式 指全域性的單例例項在第一次被使用時構建 餓漢式 指全域性的單例例項在類裝載時構建 日常我們使用的最多也是懶漢式,懶漢式是按需載入,能夠做到資源的最大利用 懶漢式 雖然這樣寫沒什麼問題,但是如果是多執行緒時可能出現問題了,如果多個執行緒同...