單例模式
單例模式的特點:
- 構造函數(shù)不對外開放纫溃,一般為Private
- 通過一個靜態(tài)方法返回一個單例類對象
- 確保單例類的對象有且只有一個,尤其是多線程的情況下赁酝。
- 確保單例類對象在反序列化時不會重新構造對象犯祠。
餓漢式
public class Singleton{
//私有化構造函數(shù)
private Singleton(){}
//定義私有化變量
private static Singleton instance;
//靜態(tài)方法提供獲取接口
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
餓漢式的特點
優(yōu)點:
- 只有在使用時才會被實例化,在一定程度上節(jié)約了資源酌呆,
缺點:
- 第一次實例化的時候需要及時衡载,需要的時間較長,反應較慢隙袁,最大的問題在于每次調(diào)用的時候都需要進行同步痰娱,造成了不必要的開銷。
Double Check Lock (DCL)實現(xiàn)單例模式
public class Singleton {
//定義私有化變量(靜態(tài))
private static Singleton mInstance = null;
//定義私有化構造參數(shù)
private Singleton(){}
//提供靜態(tài)方法獲取到單例類
public static Singleton getSingleton(){
if(mInstance == null){
synchronized(Singleton.class){
if(mInstance == null){
mInstance = new Singleton();
}
}
}
return mInstance;
}
}
但A線程執(zhí)行到mInstance = new Singleton()的時候菩收。做了如下三件事:
- 給Singleton的實例分配內(nèi)存梨睁,
- 調(diào)用Singleton()的構造函數(shù),初始化成員字段娜饵,
- 將mInstance對象指向分配的內(nèi)存空間(此時的mInstance不為null)
在JDK5.0之前 是無法保證1-2-3這樣的循序執(zhí)行的坡贺,可能會出現(xiàn)1-3-2.如果A線程中先到3第三點,此時切換了B線程,B線程就不會去初始化一些狀態(tài)遍坟。自己拿走mInstance拳亿,此時的單例模式就會失效。
JDK5.0以后的版本愿伴,只需要把mInstance的定義修改成private volatile static Singleton mInsance = null ,就能確保每次獲取的mInstance的實例都是從主內(nèi)存中獲取到的肺魁。當然volatile會影響一些性能,但是這是比較值得的操作隔节。
DCL的特點:
優(yōu)點
- 資源利用率高鹅经,
缺點:
- 第一次加載較慢,在高并發(fā)環(huán)境下有一些問題官帘。
上述的這種優(yōu)化方式還是存在的一些問題瞬雹。
最好的優(yōu)化方式如下:
public class Singleton {
//定義私有化構造參數(shù)
private Singleton(){}
//提供靜態(tài)方法獲取到單例類
public static Singleton getSingleton(){
return SingletonHolder.mInstance;
}
//定義私有化變量(靜態(tài))
private static class SingletonHolder {
private static final Singleton mInstance = new Singleton();
}
}
當?shù)谝淮渭虞dSingleton類的時候并不會初始化mInStance,只有在第一次調(diào)用Singletond的getSingleton的時候才會導致mInstance被初始化,因此刽虹,第一次在調(diào)用getSingleton的方法的時候才會導致虛擬機加載SinletonHolder類酗捌,這種方式不僅確保了線程的安全,也能夠保證單一性涌哲。同時也延遲了對象的加載胖缤。
此文章來源于<<Android源碼設計模式解析與實踐>> ,這里與大家一起分享下學習筆記阀圾。