所謂類的單例設計模式,就是採取一定的方法保證在整個的軟體系統中,對某個類
只能存在乙個物件例項,並且該類只提供乙個取得其物件例項的方法(靜態方法)。
單例模式有八種方式:
1) 餓漢式(靜態常量)
2) 餓漢式(靜態**塊)
懶漢式(執行緒不安全)
懶漢式(執行緒安全,同步方法)
懶漢式(執行緒安全,同步**塊)
6) 雙重檢查
7) 靜態內部類
8) 列舉
餓漢式(靜態常量)應用例項
步驟如下:
構造器私有化 (防止 new )
類的內部建立物件
向外暴露乙個靜態的公共方法。getinstance
**實現
優缺點class
hungrysingleton
;//內部建立乙個hungrysingleton的例項
private
static hungrysingleton instance =
newhungrysingleton()
;//提供乙個public 的靜態方法,可以返回例項
public
static hungrysingleton getinstance()
}
優點:寫法簡單,類裝載的時候就完成了例項化,避免了執行緒同步的問題
缺點: 在類裝載的時候就完成了例項化,沒有達到lazy loading的效果,如果沒用過這個例項,會造成記憶體的浪費
這種方式基於classloder機制避免了多執行緒的同步問題,不過,instance在類裝載時就例項化,在單例模式中大多數都是呼叫getinstance方法, 但是導致類裝載 的原因有很多種,因此不能確定有其他的方式(或者其他的靜態方法)導致類裝載,這時候初始化instance就沒有達到lazy loading的效果
結論:這種單例模式可用,可能造成記憶體浪費
餓漢式 通過反射或者序列化會破壞單例
優缺點說明:class
singleton
//判斷是否有singleton
public
static singleton getinstance()
return singlenton;
}}
起到了lazy loading的效果,但是只能在單執行緒下使用。
如果在多執行緒下,乙個執行緒進入了if (singleton == null)判斷語句塊,還未來得及
往下執行,另乙個執行緒也通過了這個判斷語句,這時便會產生多個例項。所以
在多執行緒環境下不可使用這種方式
結論:在實際開發中,不要使用這種方式.
優缺點說明:class
singleton
//加入同步**,解決執行緒不安全的問題
public
static
synchronized singleton getinstance()
return singlenton;
}}
解決了執行緒不安全問題
效率太低了,每個執行緒在想獲得類的例項時候,執行getinstance()方法都要進行
同步。而其實這個方法只執行一次例項化**就夠了,後面的想獲得該類例項,
直接return就行了。方法進行同步效率太低
優缺點說明:class
singleton
//雙重判斷
public
static singleton getinstance()
}}return singlenton;
}}
double-check概念是多執行緒開發中常使用到的,如**中所示,我們進行了兩
次if (singleton == null)檢查,這樣就可以保證執行緒安全了。
這樣,例項化**只用執行一次,後面再次訪問時,判斷if (singleton == null),
直接return例項化物件,也避免的反覆進行方法同步.
執行緒安全;延遲載入;效率較高
為什麼乙個if不行: 假如乙個執行緒進入了if (singleton == null)判斷語句塊,還未來得及往下執行,
另乙個執行緒也通過了這個判斷語句,這時便會產生多個例項
優缺點說明:class singleton
private static class singletoninstance
public static singleton getinstance()
}
這種方式採用了類裝載的機制來保證初始化例項時只有乙個執行緒。
靜態內部類方式在singleton類被裝載時並不會立即例項化,而是在需要例項化
時,呼叫getinstance方法,才會裝載singletoninstance類,從而完成singleton的
例項化。
類的靜態屬性只會在第一次載入類的時候初始化,所以在這裡,jvm幫助我們
保證了執行緒的安全性,在類進行初始化時,別的執行緒是無法進入的。
優點:避免了執行緒不安全,利用靜態內部類特點實現延遲載入,效率高
結論:推薦使用.
enum singleton
}
public
enum singleton
public
void
setobjname
(string objname)
public
static
void
main
(string[
] args)
}catch
(exception e)
}}
該實現可以防止反射攻擊。在其它實現中,通過 setaccessible() 方法可以將私有建構函式的訪問級別設定為 public,然後呼叫建構函式從而例項化物件,如果要防止這種攻擊,需要在建構函式中新增防止多次例項化的**。該實現是由 jvm 保證只會例項化一次,因此不會出現上述的反射攻擊。firstname
secondname
secondname
secondname
該實現在多次序列化和序列化之後,不會得到多個例項。而其它實現需要使用 transient 修飾所有字段,並且實現序列化和反序列化的方法。
單例模式總結
三種實現單例模式的對比 1.volatile關鍵字不但可以防止指令重排,也可以保證執行緒訪問的變數值是 主記憶體中的最新值 有關volatile的詳細原理,我在以後的漫畫中會專門講解。2.使用列舉實現的單例模式,不但可以防止利用反射強行構建單例物件 可以而且在列舉類物件被 反序列化 的時候,保證反序...
單例模式總結
單例模式的使用有乙個必要的條件,在乙個系統要求乙個類只有乙個例項時才應當使用單例模式。在懶漢式單例的時候為什麼要進行執行緒的控制呢?package 單例模式.懶漢模式 public class lazysingleton synchronized public lazysingleton getin...
單例模式總結
一 單例模式 singleton pattern 單例模式只涉及到乙個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。並且提供了訪問其唯一物件的方式,可以直接訪問,不需要在外部例項化該類的物件。1 單例模式可總結為以下三點 1 構造方法使用private私有化 保證外部無法new出例項...