設計模式 單例模式詳解(邊邊奮鬥史)

2021-10-09 11:58:09 字數 3428 閱讀 8136

單例類例項化出來的物件是堆裡的乙個物件,且是同乙個物件

使用場景:

當物件需要頻繁的建立和銷毀的時候,單例可以提高效能

優點:

.只有乙個例項物件,可以節省很多空間。

.物件不會被重複的 new ,降低了對系統資源的重複占用,提高了效能。

缺點:

.只有乙個物件的話,無疑擴充套件性差了很多。(想擴充套件你就得來改這個 單例類)

.場景比較多的時候,單例就顯得很無力了,根本無法應對,這時候還是不要使用單例了

.配合連線池時,不推薦使用,單例又不會死,一直來,池子就滿了。

/**

* @classname hungary 餓漢式單例

* @description 最基本的單例模式

* @author skysong

* @date 2020-09-15 22:09

*/public

class

hungary

//先把物件 new 出來

/** * 一上來就建立物件的話 容易造成浪費空間的問題

* class 被載入時 new 就分配了空間,但我們不一定用

* 這也奠定了 懶漢式 橫空出世 的必要性

*/public

final

static hungary hungary =

newhungary()

;public

static hungary getinstance()

}

基本實現:

/**

* @classname lazyman 懶漢式 單例

* @description

* @author skysong

* @date 2020-09-15 22:24

*/public

class

lazyman

//先不例項化物件

public

static lazyman lazyman;

//當呼叫時,再建立

public

static lazyman getinstance()

return lazyman;

}}

分析問題:

如果系統是單執行緒執行的話,這個寫法沒有問題。 但多執行緒就會出現問題……

我們用 10 個執行緒併發 測試一下

public

class

lazyman

public

static lazyman lazyman;

public

static lazyman getinstance()

return lazyman;

}public

static

void

main

(string[

] args)}.

start()

;}}}

結果不一,甚至出現多個 例項

thread-1

thread-2

thread-0

process finished with exit code 0

這時需要引出我們的 dcl懶漢式

/**

* @classname lazyman dcl懶漢式 單例

* @description 加入鎖,解決多執行緒併發 單例變多例 問題

* @author skysong

* @date 2020-09-15 22:24

*/public

class

lazyman

public

static lazyman lazyman;

//dcl懶漢式(雙重檢測,一層加鎖)

public

static lazyman getinstance()

}}return lazyman;

}public

static

void

main

(string[

] args)}.

start()

;}}}

分析問題:

new 物件的過程 不是乙個原子性操作!

過程如下:

1.分配空間

2.初始化(執行構造方法)

3.讓 引用 指向這個空間

當發生指令重排的時候,會出現問題:

我們希望的執行順序時 1->2->3

但 cpu 為了提高效率,有可能會 執行為 1->3->2

此時,引用已經指向了空間(lazyman 在這一時刻後就不在是 null 了),但這個空間還沒有完成初始化

為了解決這個問題,剛才的**需要改進:(給這個物件加上volatile ,防止它指令重排 )

package single;

/** * @classname lazyman 懶漢式 單例

* @description

* @author skysong

* @date 2020-09-15 22:24

*/public

class

lazyman

public

volatile

static lazyman lazyman;

//dcl懶漢式(雙重檢測,一層加鎖)

public

static lazyman getinstance()

}}return lazyman;

}public

static

void

main

(string[

] args)}.

start()

;}}}

在內部類裡呼叫,這樣別人再怎麼呼叫外部類都不會影響到單例。

/**

* @classname outer

* @description

* @author skysong

* @date 2020-09-15 23:53

*/public

class

outer

public

static outer getinstance()

public

static

class

inner

}

設計模式 單例模式詳解

1.懶漢式,執行緒不安全 public class singletonpattern 懶漢式,執行緒不安全 private static singletonpattern instance public static singletonpattern getinstance return insta...

設計模式 單例模式詳解

單例模式 singleton 保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點。通常我們可以讓乙個全域性變數使得乙個物件被訪問,但它不能防止你例項化多個物件。乙個最好的辦法就是,讓類自身負責儲存它的唯一例項。這個類可以保證沒有其他例項可以被建立,並且它可以提供乙個訪問該例項的方法。我們知道,o...

單例設計模式(詳解)

模式 模式就是解決一類問題的固定步驟 單例設計模式 保證乙個類在記憶體中只有乙個物件 舉例 多個瀏覽器向伺服器傳送請求,只建立乙個servlet物件處理相應的請求,而不是每接收乙個請求,就建立乙個servlet物件 1.餓漢單例設計模式 1.私有化建構函式 2.宣告本類的引用型別變數,並且使用該變數...