單例模式(Singleton) 設計模式學習筆記

2021-09-18 07:37:41 字數 3963 閱讀 9637

構造方法私有化

宣告乙個靜態私有的本類物件

給外部提供乙個靜態方法獲取物件例項

/**

* 餓漢模式

* 類被載入後物件被建立

* * 缺點:沒有懶載入效果

* * @author lixiang

* @date 2023年04月16日 - 11:05

* @history 2023年04月16日 - 11:05 lixiang create.

*/public

class

hungrysingleton

public

static hungrysingleton getinstance()

}

二.懶漢模式

/**

* 懶漢模式

* 呼叫getinstance方法後才建立物件 (延時載入、懶載入)

* * @author lixiang

* @date 2023年04月16日 - 11:13

* @history 2023年04月16日 - 11:13 lixiang create.

*/public

class

lazysingleton

public

static lazysingleton getinstance()

return lazysingleton;

}}

三.雙重校驗鎖

*

** 雙重校驗鎖

* 較常用

* 優點:執行緒安全

* 效率較高

* 延遲載入 **

@author lixiang

*@date

2023年04月16日 -11:

14*@history

2023年04月16日 -11:

14 lixiang create.*/

public

class

doublechecksingleton

public

static doublechecksingleton getinstance()

}}return doublechecksingleton;

}

這裡重點說下雙重校驗鎖模式,為什麼要進行雙重校驗?為什麼加volatile關鍵字?

容我給你一一道來:1.如果我們去掉第乙個if (null == doublechecksingleton)校驗,聰明的你肯定發現了**是可以在併發情況下正常執行的,因為有synchronized來保證我們的執行緒安全。既然用了synchronized那必然會損耗效能,因為一旦有執行緒進入了synchronized(doublechecksingleton.class){}塊那後續執行緒就需要阻塞等待。那我們如何在此基礎上來提高效能呢?於是就有了第乙個if (null == doublechecksingleton)校驗。

2.如果我們去掉第二個if (null == doublechecksingleton)校驗,此時**就有問題了,問題出在**呢?

假設當doublechecksingleton == null時來了兩個執行緒a、b同時到達第乙個if (null == doublechecksingleton)校驗,毫無疑問順利通過校驗執行if裡面的方法,這時因為synchronized的緣故只能有乙個執行緒進入另乙個執行緒等待。假設a執行緒進入了synchronized塊執行了doublechecksingleton = new doublechecksingleton();結束後,b執行緒再次執行doublechecksingleton = new doublechecksingleton();顯然這違背了我們單例模式的初衷。

3.如果我們去掉volatile關鍵字,此時**也是有問題的。在jvm中建立物件和賦值操作是分開進行的,也就是說doublechecksingleton = new doublechecksingleton();語句是分三步執行的:

1). 分配記憶體空間。

2). 初始化物件。

3). 將doublechecksingleton指向剛分配好的記憶體位址。

但是jvm並不保證這三個操作的先後順序,也就是說有可能jvm會按照1–>3–>2來執行。這樣就可能出錯了,我們以a、b兩個執行緒為例:

a) a執行緒先進來,由於doublechecksingleton == null,a執行緒進入了第乙個if判斷,然後進入synchronized塊,並執行doublechecksingleton = new doublechecksingleton();

b) 由於jvm內部的優化機制,jvm先分出了一些記憶體,並賦值給doublechecksingleton (注意此時jvm還沒有初始化這個例項),此時a執行緒切換到b執行緒。

c) b進行第乙個if判斷,由於此時doublechecksingleton != null,因此它馬上return doublechecksingleton;並將結果返回給呼叫該方法的程式。這時b執行緒打算使用doublechecksingleton例項,卻發現它沒有被初始化,於是錯誤發生了。

volatile關鍵字足矣另寫一篇部落格,本文不對其進行具體展開了,這裡我們利用的是:volatile變數的寫操作,不允許和它之前的讀寫操作打亂順序;對volatile變數的讀操作,不允許和它之後的讀寫亂序。如果有時間我再另寫一篇部落格深入**一下volatile關鍵字。

四.靜態內部類

/**

* * 靜態內部類

* * 類的靜態屬性只會在第一次載入類的時候初始化,所以在這裡,jvm幫助我們保證了執行緒的安全性,

* 在類進行初始化時,別的執行緒是無法進入的

* * 優點:懶載入效果

* 執行緒安全

* 效率高

* * @author lixiang

* @date 2023年04月16日 - 14:52

* @history 2023年04月16日 - 14:52 lixiang create.

*/public

class

staticinnersingleton

private

static

class

singletonholder

public

static staticinnersingleton getinstance()

}

五.列舉類

/**

* 列舉類

* 優點:避免多執行緒同步問題

* 防止反序列化重新建立新的物件

*

* @author lixiang

* @date 2023年04月16日 - 14:55

* @history 2023年04月16日 - 14:55 lixiang create.

*/public

enum enumsingleton

總結是對學習的檢驗、沉澱與昇華,如果有問題還請不吝賜教!!!

設計模式 單例Singleton

定義 確保某乙個類只有乙個例項,而且自行例項化並向整個系統提供這個例項。使用場景 確保某個類有且只有乙個物件的場景,例如建立乙個物件需要消耗的資源過多,如要訪問 io 和資料庫等資源。以earth為例,簡單的單例模式可以寫成如下形式。public class earth public earth g...

單例設計模式(singleton)

單例設計模式的概念 作為物件建立模式,檔裡模式確保某個類只有乙個例項物件,而且自行建立例項並向整個系統提供這個例項。這個類稱為單例類!單例模式的提點 1,單例類只能有乙個例項 2,單例類的唯一例項必須自己建立 3,單例類必須向系統提供這個唯一的例項 餓漢單例類 public class eagers...

設計模式 單例Singleton

若是你希望自己寫的程式中的某個類只能有乙個相對應的例項,那麼這個時候就要用到單例模式了。單例模式是一種非常常見的設計模式,實現方法有好幾種,下面將一一介紹 1.懶漢式 public class singleton public static singleton getinstance return ...