JAVA設計模式之單例模式

2021-07-24 21:31:35 字數 3588 閱讀 8196

1特點

單例類只能有乙個例項。

單例類必須自己建立自己的唯一例項。

單例類必須給所有其他物件提供這一例項。

單例模式確保某個類只有乙個例項,而且自行例項化並向整個系統提供這個例項。在計算機系統中,執行緒池、快取、日誌物件、對話方塊、印表機、顯示卡的驅動程式物件常被設計成單例。這些應用都或多或少具有資源管理器的功能。每台計算機可以有若干個印表機,但只能有乙個printer spooler,以避免兩個列印作業同時輸出到印表機中。每台計算機可以有若干通訊埠,系統應當集中管理這些通訊埠,以避免乙個通訊埠同時被兩個請求同時呼叫。總之,選擇單例模式就是為了避免不一致狀態,避免政出多頭。

單例模式有懶漢式單例和餓漢式單例兩種模式。

懶漢式單例:

package ******;

//懶漢式單例類.在第一次呼叫的時候例項化自己

public

class

lazysingleton

extends

thread

private

static lazysingleton singleton = null;

// 靜態工廠方法

public

static lazysingleton getinstance(string name)

// }

}return singleton;

}}

餓漢式單例模式

package ******;

//餓漢式單例類.在類初始化時,已經自行例項化

public

class singleton

public

static singleton getinstance()

}

懶漢單例模式與餓漢單例模式的比較如下:

1、餓漢式是執行緒安全的,在類建立的同時就已經建立好乙個靜態的物件供系統使用,以後不在改變。懶漢式如果在建立例項物件時不加上synchronized則會導致對物件的訪問不是執行緒安全的。

2、從實現方式來講他們最大的區別就是懶漢式是延時載入,他是在需要的時候才建立物件,而餓漢式在虛擬機器啟動的時候就會建立,餓漢式無需關注多執行緒問題、寫法簡單明瞭、能用則用。但是它是載入類時建立例項、所以如果是乙個工廠模式、快取了很多例項、那麼就得考慮效率問題,因為這個類一載入則把所有例項不管用不用一塊建立。

接下來我們使用多執行緒測試懶漢模式和餓漢模式

懶漢模式

package ******;

//懶漢式單例類.在第一次呼叫的時候例項化自己

public

class

lazysingleton

extends

thread

private

static lazysingleton singleton = null;

// 靜態工廠方法

public

static lazysingleton getinstance(string name)

// }

}return singleton;

}}

多執行緒**

package ******;

public

class

threadtest

extends

thread

public

void

run()

}

測試**

package ******;

public

class testsingleton

}}

實驗結果:

3懶漢

2懶漢1懶漢

0懶漢5懶漢

4懶漢

可以看到懶漢模式不是執行緒安全的。

餓漢模式

package ******;

//餓漢式單例類.在類初始化時,已經自行例項化

public

class singleton

public

static singleton getinstance()

}

多執行緒

package ******;

public

class

threadtest

extends

thread

public

void

run()

}

測試**

package ******;

public

class testsingleton

}}

實驗結果:

this
可以看出是餓漢模式是執行緒安全的。

下面介紹三種把懶漢模式程式設計執行緒安全的方法。

1、在getinstance方法上加同步

public

static

synchronized singleton getinstance()

return singleton;

}

2、雙重檢查鎖定

// 雙重檢查鎖定不是執行緒安全的,如果要用這種方式,需要使用volatile關鍵字。

private

static

volatile singleton singleton = null;

public

static singleton getinstance() }}

return singleton;

}

3、靜態內部類

public

class singleton

private

singleton()

public

static final singleton getinstance()

}

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

第2種,在getinstance中做了兩次null檢查,確保了只有第一次呼叫單例的時候才會做同步,但是不是執行緒安全的,如果要用這種方式,需要使用volatile關鍵字。可以避免了每次都同步的效能損耗。

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

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

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

但是在工廠模式下快取了很多例項、那麼就得考慮效率問題,因為這個類一載入則把所有例項不管用不用一塊建立,這個時候使用餓漢模式就很耗記憶體。

java設計模式之單例模式

單位面試題目中有一道關於單例模式的題目.大多數參加筆試的同事都會寫出getinstance這個函式,但是當我問起什麼情況下需要使用單例 單例具體有什麼好處的時候 static函式也可以構建唯一例項,為什麼還需要單例.從使用單例的經驗來看,如下場景下,個人感覺應該使用單例 1.如果需要構建乙個工具類,...

java設計模式 之 單例模式

單例模式 有些類在程式執行過程中只需要儲存乙個例項,比如檔案管理類,音訊管理類,那麼我們如何實現乙個單例類呢?有以下幾點 1 定義乙個靜態變數 2 建構函式私有化 3 提供乙個public 靜態方法,獲取這個例項 4 一定要做執行緒同步 public static class singleton p...

Java設計模式之單例模式

說到單例模式 大家一定非常熟悉 這是最常見也是設計模式中相對簡單 好理解的設計模式 今天就跟大家掰一掰單例模式 單例模式確保某個類只有乙個例項 應用場景 執行緒池 快取 等物件常常被設計成單例 然而單例分兩種 1 惡漢式 2 懶漢式 我們先來看下 惡漢式 public class singleton...