單例模式學習筆記

2021-10-05 09:28:46 字數 3926 閱讀 8359

靜態內部類單例

反射破壞單例

序列化破壞單例

註冊式單例

threadlocal 執行緒單例

單例模式(singleton pattern)是指確保乙個類在任何情況下都絕對只有乙個例項

public

class

hungrysingleton

public

static hungrysingleton getinstance()

}

懶漢式單例,在類載入時就建立了單例物件,絕對執行緒安全

優點:不需要加鎖就能保證執行緒安全,效率高

缺點:不管有沒有呼叫都會建立單例物件,可能造成空間的浪費

public

class

lazy******singleton

private

static lazy******singleton lazy = null;

public

static lazy******singleton getinstance()

return lazy;

}}

餓漢式單例,需要呼叫時才建立

這種方式無法保證執行緒安全,當多個執行緒同時訪問時,可能會建立乙個以上的單例物件

我們採用synchronized關鍵字對方法進行修飾,使其變為同步方法

public

class

lazy******singleton

private

static lazy******singleton lazy = null;

public

synchronized

static lazy******singleton getinstance()

return lazy;

}}

通過這種方式,可以解決執行緒安全的問題,但是在加了鎖之後,如果多執行緒同時呼叫該方法,會造成阻塞,降低執行效率

public

class

lazydoublechecksingleton

public

static lazydoublechecksingleton getinstance()

}}return lazy;

}}

通過volatile關鍵字修飾單例物件的引用,防止建立時因為指令重排導致失敗的情況

當獲取的單例物件為空,需要建立單例物件時,呼叫同步方法建立單例物件,防止重複建立。在物件被建立了以後,呼叫時,不觸發同步方法,直接獲取單例物件,提高了效率

public

class

lazyinnerclasssingleton

//每乙個關鍵字都不是多餘的

//static 是為了使單例的空間共享

//保證這個方法不會被重寫,過載

public

static

final lazyinnerclasssingleton getinstance()

這種方法效率更高,不需要使用鎖,也避免了未使用就建立造成的空間浪費

當訪問獲取,訪問時,該內部類才初始化

public

class

lazyinnerclasssingletontest

catch

(exception e)

}}

為了防止被反射破壞,我們修改它的構造方法,當單例物件已經存在時,丟擲異常

public

class

lazyinnerclasssingleton

}//每乙個關鍵字都不是多餘的

//static 是為了使單例的空間共享

//保證這個方法不會被重寫,過載

public

static

final lazyinnerclasssingleton getinstance()

//預設不載入

private

static

class

lazyholder

}

//反序列化時導致單例破壞 

public

class

seriablesingleton

implements

serializable

public

static seriablesingleton getinstance()

}//呼叫

public

class

seriablesingletontest

catch

(exception e)

}}

反序列化後的物件和手動建立的物件是不一樣的,為了防止這種情況,我們只需增加乙個readresolve()方法:

public

class

seriablesingleton

implements

serializable

public

static seriablesingleton getinstance()

private object readresolve()

}

在objectinputstream 類的 readobject()方法中,會判斷是否有無參構造方法,如果有,則會例項化。通過反射獲取readresolve()方法,返回例項,但是在該過程中,雖然返回的是乙個物件,但是仍然例項化了兩次

是將每乙個例項都登記到某乙個地方,使用唯一的標 識獲取例項

註冊式單例有兩種:一種是列舉註冊,一種是容器註冊

public

enum enumsingleton

public

void

setdata

(object data)

public

static enumsingleton getinstance()

}

由於列舉語法的特殊性,可以防止反序列化破壞單例,也可以防止反射破壞,具體原因,有興趣可以研究一下原始碼

public

class

containersingleton

private

static map

ioc =

newconcurrenthashmap

();public

static object getbean

(string classname)

catch

(exception e)

return obj;

}else}}

}

這種方式可以儲存多個單例物件,在spring中就有使用容器式單例

public

abstract

class

abstractautowirecapablebeanfactory

extends

abstractbeanfactory

implements

autowirecapablebeanfactory

這種方式是一種特殊的單例模式,無法保障全域性物件唯一,可以保證各個執行緒中的物件唯一

public

class

threadlocalsingleton};

private

threadlocalsingleton()

public

static threadlocalsingleton getinstance()

}

ps:參考自咕泡學院設計模式學習筆記

單例模式學習筆記

單例 優點1.減少記憶體開支 2.減少效能開銷 3.寫檔案時避免資源多重占用 4.優化共享資源訪問 缺點1.自行例項化的特點導致無法擴充套件,只能修改原始碼 2.對測試不利,只有全部完成單例 才能測試 3.與單一職責原則有衝突 適用1.生成唯一序列號的環境 2.整個專案需要乙個共享訪問點 3.建立物...

單例模式學習筆記

public class student 自己造乙個 靜態方法只能訪問靜態成員變數,加靜態 為了不讓外界直接訪問修改這個值,加private private static student s new student 提供公共的訪問方式 為了保證外界能夠直接使用該方法,加靜態 public stati...

學習筆記 單例模式

餓漢模式,即認為單例物件在單例所在的類初始化時即例項化了。因此無論該單例物件是否真正的被呼叫,都會進行例項化。例項化的操作放在靜態變數或者靜態 塊中。public class hungrysingleton private final static hungrysingleton hungrysin...