七、單例模式
阿新 • • 發佈:2018-12-09
1、定義:單例模式(Singleton),保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點。
2、什麼時候用呢?
- 資源共享的情況下
- 控制資源的情況下
- 保證唯一例項
- 可以嚴格地控制客戶怎麼訪問它。對唯一例項的受控訪問
4、實現思路
- 讓類自己儲存它唯一的例項
- 構造方法私有化
- 提供一個訪問該唯一例項的方法
5、程式設計實現
有很多種程式設計實現方式,這裡介紹兩種經典的:懶漢式、餓漢式
1)懶漢式,顧名思義,不著急例項化自己,等第一次用到的時候再例項化
a.最基本的情況
public class Singleton { private static Singleton single=null;//內部儲存自己的例項 private Singleton(){} //構造方法私有化,保證只有自己能例項化自己 // 靜態工廠方法 public static Singleton getInstance(){ //提供一個訪問自身例項的方法 if (single==null) { single=new Singleton(); //若這個例項不存在,則建立它 } return single; } }
評價:在多執行緒的情況下,這是不安全的,考慮多執行緒的安全問題,有以下三種改進方式
b. 在getInstance的方法上加同步
public class Singleton {
private static Singleton single=null;
private Singleton(){}
public static synchronized Singleton getInstance(){
if (single==null) {
single=new Singleton();
}
return single;
}
}
評價:就多了一個同步的“synchronized”關鍵字,同步方法,別的呼叫不會進入到該方法,如此保證唯一性
不足:同步是針對方法的,以後每次呼叫該方法時(即使已經建立了例項),也會進行同步,造成不必要的同步開銷。【不推薦】
c. 雙重檢查鎖定
public class Singleton { private static Singleton single=null; private Singleton(){} public static Singleton getInstance(){ if (single==null) { synchronized (Singleton.class) { if (single==null) { single=new Singleton(); } } } return single; } }
評價:先判斷例項是否存在,不存在的情況下,使用同步鎖,再檢查例項是否存在,不存在則建立。
改進之處:只有在例項不存在的情況下,才同步,減少了不必要的同步開銷
d. 靜態內部類【推薦】
public class Singleton {
private Singleton(){}
private static class LazyHolder{
private static final Singleton INSTANCE=new Singleton();
}
public static final Singleton getInstance(){
return LazyHolder.INSTANCE;
}
}
評價:在靜態內部類中例項化,利用了類載入機制,不存在多執行緒併發的問題。不一樣在於,在內部類裡面去建立物件例項,只要應用中不使用內部類,JVM就不會去載入這個單例類,也就不會建立單例物件,從而實現懶漢式的延遲載入。
唯一性的原理是什麼????
2)餓漢式,聽這名字就很飢渴,被載入的時候就迫不及待把自己例項化了
public class Singleton {
private Singleton(){}
private static final Singleton SINGLETON=new Singleton(); //直接例項化自己
public static Singleton getInstance(){
return SINGLETON;
}
}
在類建立的同時就已經建立好一個靜態的物件供系統使用,以後不再改變,所以天生是執行緒安全的。