設計模式 02 單例模式

2021-10-19 19:41:55 字數 4267 閱讀 8783

餓漢式 (靜態**塊)

懶漢式(執行緒不安全)

懶漢式(執行緒安全,同步方法)

懶漢式(執行緒不安全,同步**塊)

雙重檢查(推薦)

靜態內部類(推薦)

列舉注意事項和細節說明

所謂的單例設計模式,就是採取一定的方法,保證在整個的軟體系統中,對某個類只能存在乙個物件例項,並且該類只提供乙個取得其物件例項的方法(靜態方法)。

餓漢式就是餓了的時候馬上就要吃,懶漢式就是餓了現找不著急

實現方式

步驟如下:

構造器私有化 (防止new)

類的內部建立物件

向外暴露乙個靜態的公共方法

**實現

package singleton.type1;

/** * 餓漢式(靜態常量)

*/public

class

singleton

// 2. 本類的內部建立乙個物件例項

private

final

static singleton instance =

newsingleton()

;//3. 提供乙個公有的靜態方法,返回例項物件

public

static singleton getinstance()

}

測試**

package singleton.type1;

public

class

mytest

}

優缺點

優點:這種寫法比較簡單,就是在類裝載的時候就完成了例項化。避免了執行緒同步問題。

缺點:在類裝載的時候就完成了例項化,沒有達到lazy loading的效果,弱國從始至終未使用過這個例項,則會造成記憶體的浪費。

這種方式基於classloder機制避免了多執行緒的同步問題。不過,instance在類裝載時就例項化,在單例模式中大多數都是呼叫getinstance方法,但是導致類裝載的原因有很多種,因此不能確定有其它的方式(或者其它的靜態方法)導致類裝載,這時候初始化instance就沒有達到lazy loading 的效果

結論:這種方法可用,可能造成記憶體浪費

實現方式

package singleton.type2;

public

class

singleton

private

static singleton instance;

static

public

static singleton getinstance()

}

優缺點

這種方式和上面的方式其實類似,只不過將類的例項化過程放在了靜態**塊中,也是在類裝載的時候,就執行靜態**塊中的**,初始化類的例項。優缺點和上面是一樣的。

結論:這種單例模式可用,但是可能造成記憶體浪費

實現方式

package singleton.type3;

public

class

singleton

//提供乙個靜態的公有方法,當使用到該方法時,才去建立instance

//即懶漢式

public

static singleton getinstance()

}

優缺點

起到了lazy loading的效果,但是只能在單執行緒下使用

如果在多執行緒下,乙個執行緒進入了if(instance == null)判斷語句塊,還沒來得及往下執行,另乙個執行緒也通過了這個判斷語句,這是便會new多個例項,產生額外的不必要的開銷,所以在多執行緒環境下不可使用這種方式

結論:在實際開發中,不要使用這種方式

實現方式

package singleton.type4;

public

class

singleton

private

static singleton instance;

public

static

synchronized singleton getinstance()

}

優缺點

解決了程序不安全的問題

效率太低了,每個執行緒在想獲得類的例項時候,執行getinstance()方法都要進行同步。而其實這個方法只執行一次例項化**就夠了,後面的想獲得該例項,直接return就行了。方法進行同步效率太低

實現方式

class

singleton

private singleton instance;

public

static singleton getinstance()

}return singleton;

}}

優缺點

這種方式,本意是對懶漢式-執行緒安全同步方法實現方式的改進,因為前面同步方法的效率太低,改為同步產生例項化的**塊

但是這種同步,並不能起到執行緒同步的作用,跟第3中實現方式遇到的情形一致,接入乙個執行緒進入了if(instance == null)判斷語句塊,還未來得及往下執行,另乙個執行緒也通過了這個判斷語句,這時便會產生多個例項

結論:在實際開發中,不能使用這種方式

實現方式

package singleton.type6;

public

class

singleton

public

volatile

static singleton instance;

public

static singleton getinstance()

}return instance;

}}

volatile作用:防止指令重排,保證**的可見性,保證主存和工作記憶體同步

如果不用volatile關鍵字,有可能會出現異常。因為instance = new singleton();並不是乙個原子操作。執行緒a的操作會被編譯成三條指令:(a1)分配物件的記憶體空間 (a2)初始化物件 (a3)設定instance指向記憶體空 但是這個被返回的instace是有問題的:她還沒有被初始化,a2還沒有被執行

優缺點double-check概念是多執行緒開發中常使用到的,如**中所示,我們進行了兩次if(singleton == null)檢查,這樣就可以保證執行緒安全了

這樣,例項化**只用執行一次,後面再次訪問時,判斷if(singleton == null),直接return例項化物件,也避免的反覆進行方法同步

執行緒安全:延遲載入;效率較高

實現方式

package singleton.type7;

public

class

singleton

//寫乙個靜態內部類,該類中有乙個靜態屬性singleton

private

static

class

singletoninstance

// 提供乙個靜態的公有方法,直接返回singletoninstance.instance

public

static singleton getinstance()

}

優缺點

這種方式採用了類裝載的機制來保證初始化例項時只有乙個執行緒

靜態 內部類方式在singleton類被裝載時不會立即例項化,而是在需要例項化時,呼叫getinstance方法,才會裝載singletoninstance類,從而完成singleton的例項化

類的靜態屬性指揮在第一次載入類的時候初始化,所以在這裡,jvm幫助我們保證了執行緒的安全性,在類進行初始化時,別的程序是無法進入的

優點:避免了執行緒不安全,利用靜態內部類特點實現延遲載入,效率高

結論:推薦使用

實現方式

enum singleton 

}

測試**

@test

public

void

test()

優缺點單例模式保證了系統記憶體中該類只存在乙個物件,節省了系統資源,對於一些需要頻繁建立銷毀的物件,使用單例模式可以提高系統效能

當想例項化乙個單例類的時候,必須要記住使用相應的獲取物件的方法,而不是使用new

單例模式使用的場景:需要頻繁的進行建立和銷毀的物件、建立物件時耗時過多或耗費資源過多(即:重量級物件),但又經常用到的物件、工具類物件、頻繁訪問資料庫或檔案的物件(比如資料來源、session工廠等)

設計模式 02 單例模式

1 餓漢模式 宣告靜態物件時,已經初始化。public class singleton public static singleton getinstance 2 懶漢模式 第一次呼叫getinstance時進行初始化。缺點 每次呼叫getinstance都進行同步,造成不必要的同步開銷。publi...

設計模式 02 單例模式

參考 需要某個類只保留乙個物件,如資料庫連線 網路連線 執行緒池等。只能有乙個例項 單例類必須建立自己的唯一例項 單列類向其他物件提供這一例項 單例可以繼承與被繼承,方法可以重寫。靜態類不行 單例產生的物件常駐記憶體。靜態類物件執行後會被釋放,被gc清理 單例模式可以延遲載入,靜態類在第一次執行時被...

設計模式 02 單例模式

描述 singleton 模式要求乙個類有且僅有乙個例項,並且提供了乙個全域性的訪問點 方式1 sealed class singleton 這種方式不能實現延遲初始化 呼叫時才進行初始化 它在編譯時就初始化出了乙個例項,sealed保證類不能被繼承。方式二 sealed class singlet...