JAVA單例模式

2021-07-27 11:51:55 字數 3395 閱讀 4377

單例設計模式

singleton是一種建立型模式,指某個類採用singleton模式,則在這個類被建立後,只可能產生乙個例項供外部訪問,並且提供乙個全域性的訪問點。

核心知識點如下:

(1) 將採用單例設計模式的類的構造方法私有化(採用private修飾)。

(2) 在其內部產生該類的例項化物件,並將其封裝成private static型別。

(3) 定義乙個靜態方法返回該類的例項。

/** 

* 方法一

* 單例模式的實現:餓漢式,執行緒安全 但效率比較低

*/public

class

singletontest

// 將自身的例項物件設定為乙個屬性,並加上static和final修飾符

private

static

final singletontest instance = new singletontest();

// 靜態方法返回該類的例項

public

static singletontest getinstancei()

}

方法一就是傳說的中的餓漢模式

優點是:寫起來比較簡單,而且不存在多執行緒同步問題,避免了synchronized所造成的效能問題;

缺點是:當類singletontest被載入的時候,會初始化static的instance,靜態變數被建立並分配記憶體空間,從這以後,這個static的instance物件便一直佔著這段記憶體(即便你還沒有用到這個例項),當類被解除安裝時,靜態變數被摧毀,並釋放所占有的記憶體,因此在某些特定條件下會耗費記憶體。

/**  

*方法二

* 單例模式的實現:飽漢式,非執行緒安全

*

*/public

class

singletontest

// 定義乙個singletontest型別的變數(不初始化,注意這裡沒有使用final關鍵字)

private

static singletontest instance;

// 定義乙個靜態的方法(呼叫時再初始化singletontest,但是多執行緒訪問時,可能造成重複初始化問題)

public

static singletontest getinstance()

}

方法二就是傳說的中的懶漢模式

優點是:寫起來比較簡單,當類singletontest被載入的時候,靜態變數static的instance未被建立並分配記憶體空間,當getinstance方法第一次被呼叫時,初始化instance變數,並分配記憶體,因此在某些特定條件下會節約了記憶體;

缺點是:併發環境下很可能出現多個singletontest例項。

/**  

*方法三

* 單例模式的實現:飽漢式,執行緒安全簡單實現

*

*/public

class

singletontest

// 定義乙個singletontest型別的變數(不初始化,注意這裡沒有使用final關鍵字)

private

static singletontest instance;

// 定義乙個靜態的方法(呼叫時再初始化singletontest,使用synchronized 避免多執行緒訪問時,可能造成重的復初始化問題)

public

static

synchronized singletontest getinstance()

}

方法三為方法二的簡單優化

優點是:使用synchronized關鍵字避免多執行緒訪問時,出現多個singletontest例項。

缺點是:同步方法頻繁呼叫時,效率略低。

/**  

* 方法四

* 單例模式最優方案

* 執行緒安全 並且效率高

* */public

class

singletontest

//定義乙個靜態私有變數(不初始化,不使用final關鍵字,使用volatile保證了多執行緒訪問時instance變數的可見性,避免了instance初始化時其他變數屬性還沒賦值完時,被另外執行緒呼叫)

private

static

volatile singletontest instance;

//定義乙個共有的靜態方法,返回該型別例項

public

static singletontest getistance()

}

}

return instance;

}

}

方法四為單例模式的最佳實現。記憶體占用地,效率高,執行緒安全,多執行緒操作原子性。

餓漢式和懶漢式區別

從名字上來說,餓漢和懶漢,

餓漢就是類一旦載入,就把單例初始化完成,保證getinstance的時候,單例是已經存在的了,

而懶漢比較懶,只有當呼叫getinstance的時候,才回去初始化這個單例。

另外從以下兩點再區分以下這兩種方式:

1、執行緒安全:

餓漢式天生就是執行緒安全的,可以直接用於多執行緒而不會出現問題,

懶漢式本身是非執行緒安全的,為了實現執行緒安全有幾種寫法,分別是上面的1、2、3,這三種實現在資源載入和效能方面有些區別。

2、資源載入和效能:

餓漢式在類建立的同時就例項化乙個靜態物件出來,不管之後會不會使用這個單例,都會佔據一定的記憶體,但是相應的,在第一次呼叫時速度也會更快,因為其資源已經初始化完成,

而懶漢式顧名思義,會延遲載入,在第一次使用該單例的時候才會例項化物件出來,第一次呼叫時要做初始化,如果要做的工作比較多,效能上會有些延遲,之後就和餓漢式一樣了。

至於1、2、3這三種實現又有些區別,

第1種,在方法呼叫上加了同步,雖然執行緒安全了,但是每次都要同步,會影響效能,畢竟99%的情況下是不需要同步的,

第2種,在getinstance中做了兩次null檢查,確保了只有第一次呼叫單例的時候才會做同步,這樣也是執行緒安全的,同時避免了每次都同步的效能損耗

第3種,利用了classloader的機制來保證初始化instance時只有乙個執行緒,所以也是執行緒安全的,同時沒有效能損耗,所以一般我傾向於使用這一種。

什麼是執行緒安全?

如果你的**所在的程序中有多個執行緒在同時執行,而這些執行緒可能會同時執行這段**。如果每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。

或者說:乙個類或者程式所提供的介面對於執行緒來說是原子操作,或者多個執行緒之間的切換不會導致該介面的執行結果存在二義性,也就是說我們不用考慮同步的問題,那就是執行緒安全的。

java單例模式

第一種方法 public class singleton private static singleton singleton new singleton public static singleton getinstance 第二種方法 public class singleton private...

Java 單例模式

單例模式特點 1 單例類只能有乙個例項。2 單例類必須自己自己建立自己的唯一例項。3 單例類必須給所有其他物件提供這一例項。一 餓漢式單例 基於classloder機制避免了多執行緒的同步問題,使用較多 public class singleton 這裡提供了乙個供外部訪問本class的靜態方法,可...

Java單例模式

單例模式的意圖是為了確保乙個類有且僅有乙個例項,並為它提供乙個全域性訪問點。單例模式通過隱藏建構函式,提供物件建立的唯一入口點,從而將類的職責集中在類的單個例項中。design patterns一書中把單例模式歸類為 建立型 模式,意圖是在表明單例物件承擔了其他物件所要依賴的職責。單例模式的優點 在...