單例設計模式實作
單例設計模式:某個類只能存在一個物件實體
設計要點:
- 一個私有建構式(不能外面new,只能自己創建)
- 一個私有靜態變數(確保只有一個實體)
- 一個公共靜態函式(呼叫,用來回傳實體物件)
餓漢式
天生執行緒安全,用得也比較多
先創建實體,因為比較餓,沒有延遲加載,如果很久沒用到這個實體,就會浪費系統資源,
靜態常量餓漢式
public class Singleton {
static class Singleton{
private Singleton(){}
private final static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
}
靜態代碼塊餓漢式
public class Singleton {
private Singleton() {
}
private static Singleton instance;
static { // 在靜態代碼塊中,創建單例物件
instance = new Singleton();
}
public static Singleton getInstance() {
return instance;
}
}
懶漢式
用的時候再創建實體,因為比較懶
執行緒不安全懶漢式
多執行緒下,一個執行緒進入了if判斷陳述句塊,還未來得及往下執行,另一個執行緒也通過了這個判斷陳述句,這時便會產生多個實體,所以在多執行緒環境下不可使用這種方式
public class Singleton {
private static Singleton instance;
private Singleton() {}
//提供一個靜態的公有方法,當使用到該方法時,才去創建實體
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
執行緒安全懶漢式
效率低,多執行緒時,每次都要進行上鎖
public class Singleton {
private static Singleton instance;
private Singleton() {}
//加入同步處理的代碼,解決執行緒安全問題
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
雙重檢測懶漢式(推薦)
執行緒安全,懶加載,效率較高
class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
volatile:保證了變數的可見性,如果發生改變,其他執行緒立馬可見
雙重檢查:
首次創建實體時,進入第二個if判斷后,還未創建實體,此時若有其他執行緒進來,通過了第一個if判斷,然后因為有synchronized,被擋在了外面,
實體化代碼只執行一次,后面執行緒再次訪問時,在第一個if判斷時,就直接return實體了,
靜態內部類
執行緒安全,推薦使用
靜態內部類方式在 Singleton 類被裝載時并不會立即實體化,而是在需要實體化時,呼叫 getInstance 方法,才會裝載 SingletonInstance 類,從而完成 Singleton 的實體化.
類的靜態屬性只會在第一次加載類的時候初始化,所以在這里,JVM 幫助我們保證了執行緒的安全性,在類進行初始化時,別的執行緒是無法進入的,
外部類被加載的時候,靜態內部類不會被加載,靜態代碼塊會被加載,
public class Singleton {
private static volatile Singleton instance;
//構造器私有化
private Singleton() {}
//寫一個靜態內部類,該類中有一個靜態屬性 Singleton
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
//提供一個靜態的公有方法,直接回傳
SingletonInstance.INSTANCE
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
列舉
執行緒安全,還能防止反射和反序列化重新創建新的物件,不能延時加載
enum Singleton {
INSTANCE; //屬性
public void sayOK() {
System.out.println("ok");
}
}
使用場景
需要頻繁的進行創建和銷毀的物件,比如:工具類物件,頻繁訪問資料庫或檔案物件,
JDK原始碼Runtime類
餓漢式單例
RunTime代表一個運行環境,每個JVM行程都是對應這一個Runtime實體,此實體是由JVM為其實體化的,每個 Java 應用程式都有一個 Runtime 類實體,使應用程式能夠與其運行的環境相連接,
public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
private Runtime() {}
}
Spring依賴注入Bean實體
雙重檢查懶漢單例
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
SpringBoot原始碼中的單例
......
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/174093.html
標籤:設計模式
