安全高效的單例

2021-10-23 16:42:46 字數 2542 閱讀 3223

概述

單例設計模式,就是採取一定的方法保證在整個的軟體系統中,對某個類只能存在乙個物件例項, 並且該類只提供乙個取得其物件例項的方法(靜態方法)。單例適用於需要頻繁的進行建立和銷毀的物件、建立物件時耗時過多或耗費資源過多(即:重量級物件),但又經常用到的物件、工具類物件、頻繁訪問資料庫或檔案的物件(比如資料來源、hibernate 的 sessionfactory工廠等)。

單例的實現七種方法:

1.餓漢式(靜態變數)(推薦)

該方法在類裝載時就完成例項化,避免執行緒同步問題

但是如果該類一直沒使用,則會造成記憶體浪費(不僅getinstance會導致類裝載,其它方式也可能導致類裝載)

class

singleton

//2.使用內部建立物件例項,靜態變數

private

final

static singleton instance =

newsingleton()

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

public

static singleton getinstance()

}

2.餓漢式(靜態**塊)(推薦)

同靜態變數

class

singleton

//2.使用內部內建立物件例項,靜態變數

private

static singleton instance;

static

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

public

static singleton getinstance()

}

3.懶漢式(不推薦)

用到時才建立,達到lazing loading效果,但僅在單執行緒下使用。

多執行緒下,乙個執行緒進入if (instance == null),還沒來得及建立物件時,另乙個執行緒也通過了該if語句,會產生多個例項。

class

singleton

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

public

static singleton getinstance()

return instance;

}}

4.synchronized同步的懶漢式(不推薦)

加入synchronized同步方法,解決了併發問題,但效率太低。每個執行緒想獲得類的例項時,都要執行getinstance()方法同步,而其實只執行一次例項化**就夠了,後面想獲得該例項,直接return即可。

class

singleton

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

public

static

synchronized singleton getinstance()

return instance;

}}

5.雙重檢查(推薦使用)

雙重檢查(執行緒安全,同步方法)

兩次檢查,保證執行緒安全,第一次檢查確保同步塊**只執行一次,提高效率

class

singleton

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

public

static singleton getinstance()

}}return instance;

}}

為什麼要加volatile關鍵字?

首先進入的執行緒在建立物件時進行操作依次是:

0 new #2 給物件t分配記憶體空間,賦予屬性以預設值。

4 invokespecial #3 呼叫t的構造方法,將屬性初始化。

7 astore_1 將引用變數t指向對像t

若發生重排序,使得引用變數指向物件先於初始化執行,那麼第二個執行緒進來時先判斷物件不為空,直接將其返回,就會返回乙個半初始化的物件。

所以必須加volatile,防止指令重排。

6.靜態內部類(推薦)

靜態內部類在singleton被裝載時並不會馬上被裝載,只有在getinstance()方法被呼叫時才會被裝載,達到延遲載入的目的,類在裝載時是執行緒安全的(jvm確保類的靜態屬性只會在第一次載入類的時候初始化,類的初始化時其它執行緒無法進入)。

class

singleton

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

private

static

class

singletoninstance

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

public

static singleton getinstance()

}

7.列舉(推薦)

列舉可以避免多執行緒,防止反射和反序列化重新建立物件

enum singleton

}

單例模式 層層剖析尋找最高效安全的單例

什麼是單例?它的運用場景是什麼?單例模式是指保證在系統中只存在某類唯一物件。運用場景隨處可見,例如工具類 spring容器預設new物件等。單例模式有幾種實現方式?餓漢式 懶漢式 雙重檢查鎖式 內部類式 列舉式。推薦使用方式?餓漢式 內部類式。餓漢式顧名思義餓,那麼當應用程式一開始類載入,類的物件立...

單例模式 層層剖析尋找最高效安全的單例

什麼是單例?它的運用場景是什麼?單例模式是指保證在系統中只存在某類唯一物件。運用場景隨處可見,例如工具類 spring容器預設new物件等。單例模式有幾種實現方式?餓漢式 懶漢式 雙重檢查鎖式 內部類式 列舉式。推薦使用方式?餓漢式 內部類式。餓漢式顧名思義餓,那麼當應用程式一開始類載入,類的物件立...

單例模式 層層剖析尋找最高效安全的單例

什麼是單例?它的運用場景是什麼?單例模式是指保證在系統中只存在某類唯一物件。運用場景隨處可見,例如工具類 spring容器預設new物件等。單例模式有幾種實現方式?餓漢式 懶漢式 雙重檢查鎖式 內部類式 列舉式。推薦使用方式?餓漢式 內部類式。餓漢式顧名思義餓,那麼當應用程式一開始類載入,類的物件立...