單例模式,顧名思義要確定某一個類隻能存在一個執行個體,類要自行建立自己的唯一執行個體,并且要像整個系統提供這個執行個體。
單例模式是為了避免不一緻的狀态,避免政出多頭的現象。是以多為具有資源管理功能的類,常見的如線程池,日志,緩存等。
編寫單例模式要保證:
1.單例隻能有一個執行個體
2.單例必須自己建立自己的唯一執行個體
3.單例類必須給其他對象提供方法通路這唯一執行個體
單例模式 懶漢式
public class Singleton {
//私有的空構造方法,禁止除本類之外的通路
private Singleton(){};
//初始化一個空的執行個體
private static Singleton single = null;
//提供靜态擷取Singleton方法供其他類擷取執行個體
public static Singleton getInstance(){
if(single == null){
this.single = new Singleton();
}
return this.single;
}
}
外部類在調用getInstance的時候才會建立單例執行個體,是以被稱為懶漢式。
此方法沒有保證線程安全問題,當多個線程同時調用getInstance方法,可能産生多個Singleton執行個體。
線程安全的懶漢式單例模式
1.為getInstance添加synchronized鎖,此種方式雖然能保障多線程下可以正常工作,也有lazy loading。但是由于添加了synchronized鎖,導緻效率很慢,而且在大多數情況下是不需要進行同步的。
public class Singleton {
private Singleton(){};
private static Singleton single = null;
//添加synchronized鎖
public static synchronized getInstance(){
if (this.single == null){
this.single = new Singleton();
}
return this.single;
}
}
2.添加雙重校驗鎖,此方法為上一個的更新版,在getInstance中做了兩次null檢查,確定了隻有第一次調用單例的時候才會做同步,這樣也是線程安全的,同時避免了每次都同步的性能損耗。
public class Singleton {
private Singleton(){};
private static Singleton single = null;
//添加雙重驗證synchronized鎖
public static getInstance(){
if (this.single == null){
synchronized(Singleton.class){
if(this.single == null){
this.single = new Singleton();
}
}
}
return this.single;
}
}
3.使用靜态内部類,比較推薦。這種方式利用了calssloder機制保證初始化instance時隻有一個程序,這個方式在加載Singleton類的時候,instance可以沒有被初始化,因為LazyHolder類并沒有被使用,隻有當調用getInstance方法時才會顯示裝載LazyHolder類,進而執行個體化instance。
public class Singleton {
private Singleton(){};
//建立靜态内部類
public static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
//使用static final保證single唯一
private static final Singleton single = new Singleton();
//提供靜态方法供外部調用
public static final getInstance(){
return LazyHolder.INSTANCE;
}
}
單例模式 餓漢式
public class Singleton {
//建立私有的構造方法
private Singleton(){};
//使用static final保證single唯一
private static final Singleton single = new Singleton();
//提供靜态方法供外部調用
public static getInstance(){
return this.single;
}
}
餓漢式在類初始化的時候就已經建立了唯一的靜态對象供其他類調用,是以是線程安全的。但是因為需要在類初始化的時候就建立靜态對象,占用記憶體空間,在執行個體需要大量資源的時候不推薦使用。
單例模式 枚舉式
//enum是java1.5之後添加的
public enum RegisterSingleton {
INSTANCE;
public RegisterSingleton getInstance() {
return INSTANCE;
}
}
最牛逼高端大氣上檔次的單例模式,也是effective java推薦使用的方式,但是隻支援java1.5及以上版本使用
通過靜态内部類實作單例模式
public class InnerSingleton {
public static InnerSingleton getInstance(){
return SingLetonHolder.INNER_SINGLETON;
}
private static class SingLetonHolder{
private static final InnerSingleton INNER_SINGLETON = new InnerSingleton();
}
}