設計模式 單例模式

2021-09-28 17:37:17 字數 2385 閱讀 9895

單例模式 (singleton pattern)使用的比較多,比如我們的 controller 和 service 都是單例的,但是其和標準的單例模式是有區別的。這種型別的

設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。這種模式涉及到乙個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。單例模式的結構很簡單,只涉及到乙個單例類,這個單例類的構造方法是私有的,該類自身定義了乙個靜態私有例項,並向外提供乙個靜態的公有函式用於建立或獲取該靜態私有例項。

單例模式分為懶漢單例和餓漢單例;餓漢單例**很簡單,顧名思義,餓漢單例就是類初始化的時候就將該單例建立,示例**如下:

public class singleton 

//通過該方法獲得例項物件

public static singleton getsingleton()

//類中其他方法,盡量是 static

public static void dosomething()

}

但是懶漢單例就不那麼簡單了,懶漢單例是在訪問這個類的例項的時候先判斷這個類的例項是否建立好了,如果沒建立好就要先建立這個單例。也就是說懶漢單例是第一次訪問的的時候建立單例,而不是初始化階段。這將會導致乙個問題,如果在多執行緒場景下,多個執行緒同時訪問這個單例都發現其未被建立,那麼這些執行緒就會分別建立例項,那麼這個單例模式就不那麼單例了——例項被多次建立。在阿里開發手冊中有兩條就是和懶漢單例相關的,告訴我們要如何去避免這種情況,第六節的第一條 和第十二條:

(六)併發處理

1.【強制】獲取單例物件需要保證執行緒安全,其中的方法也要保證執行緒安全。

說明:資源驅動類、工具類、單例工廠類都需要注意。

【推薦】在併發場景下,通過雙重檢查鎖(double-checked locking)實現延遲初始化的優

決方案中較為簡單一種(適用於 jdk5 及以上版本),將目標屬性宣告為 volatile 型。

反例:

class singleton   

return helper;

} // other methods and fields...

}

其中它的雙重檢測鎖指的是這段**:

if (helper == null) synchronized(this)
這裡如果不用雙重檢測鎖的話只能在整個gethelper方法上上鎖,因為這個方法必須要保證在併發情況下只有乙個執行緒會執行helper = new helper();,這段**。也就是說** 會成為這樣:

public synchronized helper gethelper()   

return helper;

}

整個方法上鎖效能明顯是不好的,鎖的粒度變大了;雙重檢查鎖裡面為什麼要做兩次 if 判斷呢,這個問題留給讀者思考,並不是特別難的問題。但是反例裡面沒有考慮到可見性的問題——假設a執行緒和b執行緒同時訪問gethelper方法,然後 b 執行緒被阻塞住,a執行緒發現helper未被例項化,於是執行new方法,然後釋放鎖;此時b執行緒進來,或許我們直觀的感受是b執行緒發現屬性被例項化直接返回helper,但實際上不是,當乙個執行緒修改了執行緒共享的公共資源的時候(此處是helper屬性)其他執行緒未必會被通知到屬性被修改,因此b執行緒有可能發現helper還是null 也有可能b執行緒知道 helper 被賦值了。使用volatile就可以避免這種情況的發生。因此正確的**應該是這樣的:

class singleton   

// other methods and fields...

}

如果你jvm模型理解的還算透徹的話,這個問題就很好回答。通俗的說就是 service 或者 controller 裡面都是方法,沒有基本資料型別和字串這樣的屬性。用專業術語回答就是:它們都是無狀態的bean。其實bean的概念是在ejb規範裡面提出來的,後面就被沿用了。感興趣的小夥伴可以去查查資料,了解一下ejb規範裡面的三種型別的bean。這裡說一下什麼是無狀態的bean,什麼是bean的狀態。

有狀態就是有資料儲存功能。有狀態物件(stateful bean),就是有例項變數的物件,可以儲存資料,是非執行緒安全的。在不同方法呼叫間不保留任何狀態。無狀態就是一次操作,不能儲存資料。無狀態物件(stateless bean),就是沒有例項變數的物件.不能儲存資料,是不變類,是執行緒安全的。其

設計模式 單例模式

單例模式 singleton pattern 是乙個比較簡單的模式,其定義如下 ensure a class has only one instance,and provide a golbal point of acess to it.確保某乙個類只有乙個例項,而且自行例項化並且向整個系統提供這個...

設計模式 單例模式

class testsingleton static public function instance return self testsingleton private function clone public function setsinvar sinvar public function ...

設計模式 單例模式

單例模式的目的是保證類在系統中只被例項化一次,由該唯一的例項來為系統提供服務.單例模式主要用於保證服務的統一,比如獲取統一的編號服務,模仿oracle的序列生成等.但單例的使用需要謹慎,特別是在需要作負載均衡的地方,因為這種程式級的單例模式實際上只能保證在乙個應用中為單例.如果被多個應用載入,還是會...