Java設計模式(一)單例模式
1、基本介紹
-
單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。在整個程式的執行過程中,所有該類的引用都指向同一個例項。
-
-
整個程式執行過程中只有一個例項。
-
類必須在內部建立自己的例項。
-
該類必須提供一個公共方法供其它類獲取這個例項。
-
-
好處:
-
防止一個類被頻繁的建立和銷燬,降低了系統的資源消耗,因為只有一個例項。
-
避免對資源的多重佔用。
-
2、應用場景
-
要求生產唯一序列號。
-
WEB 中的計數器,不用每次重新整理都在資料庫里加一次,用單例先快取起來。
-
建立的一個物件需要消耗的資源過多,比如 I/O 與資料庫的連線等。
二 、單例模式的七種實現
1、餓漢式-靜態常量
class Singleton{
//1.構造器私有化
private Singleton(){
}
//2.本類內部宣告物件並初始化
private final static Singleton instance = new Singleton();
//3.對外提供一個公有的靜態方法,返回例項物件
public static Singleton getInstance(){
return instance;
}
}
-
餓漢式-靜態常量
-
構造器私有;
-
內部宣告靜態常量並初始化;
-
提供public方法獲取例項。
-
-
優點:
-
寫法簡單;
-
類載入時完成例項化,執行緒安全。
-
-
缺點:
-
沒有實現懶載入,如果沒有用到該類,則會造成資源浪費。
-
2、餓漢式-靜態程式碼塊
class Singleton{
//1.構造器私有化
private Singleton(){
}
//2.本類內部宣告物件
private static Singleton instance;
static {
//靜態程式碼塊中物件例項化
instance = new Singleton();
}
//3.對外提供一個公有的靜態方法,返回例項物件
public static Singleton getInstance(){
return instance;
}
}
-
餓漢式-靜態程式碼塊
-
構造器私有;
-
內部宣告靜態常量;
-
通過靜態程式碼塊初始化
-
提供public方法獲取例項。
-
-
優點:
-
寫法簡單;
-
類載入時完成例項化,執行緒安全。
-
-
缺點:
-
沒有實現懶載入,如果沒有用到該類,則會造成資源浪費。
-
3、懶漢式-執行緒不安全
class Singleton{
//1.構造器私有化
private Singleton(){
}
//2.本類內部宣告物件
private static Singleton instance;
//3.對外提供一個公有的靜態方法,第一次使用時例項化物件
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
-
懶漢式-執行緒不安全
-
構造器私有;
-
內部建立靜態常量;
-
第一次使用時例項化物件。
-
-
優點:
-
使用時載入,避免資源浪費,只能在單執行緒使用。
-
-
缺點:
-
如果多個執行緒同時進入if判空,則有可能建立多個例項,執行緒不安全。
-
4、懶漢式-同步關鍵字(執行緒安全)
class Singleton{
//1.構造器私有化
private Singleton(){
}
//2.本類內部宣告物件
private static Singleton instance;
//3.對外提供一個公有的靜態方法,第一次使用時例項化物件,並加入同步關鍵字
synchronized public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
-
懶漢式-同步關鍵字(執行緒安全)
-
構造器私有;
-
內部宣告靜態常量;
-
第一次訪問例項化物件;
-
加入synchronized同步關鍵字,每次只有一個執行緒能進入該方法。
-
-
優點:
-
執行緒安全;
-
懶載入。
-
-
缺點:
-
效率太低,每次呼叫getInstance要進行同步,不推薦使用。
-
5、懶漢式-雙重檢查(執行緒安全)
class Singleton{
//1.構造器私有化
private Singleton(){
}
//2.本類內部宣告物件,使用volatile修改其他執行緒可立即感知並且防止程式碼重排序
private static volatile Singleton instance;
//3.對外提供一個公有的靜態方法,第一次使用時例項化物件,並加入同步程式碼塊雙重檢查
public static Singleton getInstance(){
if(instance == null){
{
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
}
return instance;
}
}
-
懶漢式-雙重檢查
-
構造器私有;
-
內部宣告靜態常量並標識volatile關鍵字;
-
第一次訪問進行物件例項化,並使用雙重檢查機制。
-
-
優點:
-
懶載入;
-
執行緒安全,除了剛開始多個執行緒可能需要進行同步,後面都不需要進入同步程式碼塊,效率高,推薦使用。
-
-
缺點:
-
無。
-
6、靜態內部類
class Singleton{
//1.構造器私有化
private Singleton(){
}
//2靜態內部類
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
//3.公共方法獲取例項
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
-
靜態內部類
-
構造器私有;
-
提供靜態類;
-
提供公共靜態方法返回物件例項。
-
-
優點:
-
JVM在載入外部類時並不會載入內部類,只有顯示呼叫getInstance才會對內部類進行載入,所以提供了懶載入的效果。
-
執行緒安全,JVM載入類時是單執行緒的。
-
-
缺點:
-
無。
-
7、列舉
enum Singleton{
//屬性
INSTANCE;
}
//獲取物件
//Singleton instance = Singleton.INSTANCE;
-
列舉
-
建立列舉類;
-
提供屬性。
-
-
優點:
-
實現簡單;
-
多執行緒安全;
-
防止反序列化重新建立物件;
-
這種方式是 Effective Java 作者 Josh Bloch 提倡的方式。
-
-
缺點:
-
無。
-
三、JDK實現單例模式
-
java.lang包下Runtime類
-
使用了第一種餓漢式