標籤:列印 靜態 turn info str img 分享 null 多線程
JAVA設計模式--單例模式
- 經典單例模式的原理
1.1 意義:有些類,實際應用中往往只能有一個對象。可能用可能不用,用也只能用這一個對象,比如印表機,顯卡日誌對象等,這樣不會導致衝突,使結果一致。
1.2 問題解決:是否可以考慮靜態變數方式來實現(構造方法私人化)?或者程式員之間協商全域變數。
1.3 單例模式:確保一個類最多隻有一個執行個體,並提供一個全域訪問點。
1.4 實際操作:使用private自己內部調用
單例模式類圖:
案例:巧克力工廠
普通類中,因為工廠只有一個,但是執行個體有多個,這時會導致狀態不一致,可以考慮用單例模式。
public class ChoclateFactory { private boolean empty; private boolean boiled; private static ChoclateFactory uniqeInstance=null ; private ChoclateFactory(){ empty=true; boiled=false; } //構造類對象 public static ChoclateFactory getInstance() { //是否為空白,同事調用時保持狀態不變 if(uniqeInstance==null){ uniqeInstance=new ChoclateFactory(); } return uniqeInstance; } public void Fill() { if(empty){ //添加 empty=false; boiled=false; } } public void Boil() { if((!empty)&&(!boiled)){ //加熱 boiled=true; } } public void Drain() { if(!empty&&boiled){ //加熱 empty=true; } }}
使用過程中,會出現一些問題,例如多線程(兩個線程擷取兩個對象,無法保證唯一性)。
解決方案:①在getInstance添加一個同步鎖(保證一個線程結束後,在執行下一個線程)
public static synchronized ChoclateFactory getInstance()
但是同步鎖比較消耗資源,能解決問題,但不建議使用。
②“急切”建立執行個體
private static ChoclateFactory uniqeInstance=new ChoclateFactory() ;
調用運行時,直接建立對象,getInstance()直接返回,彌補了同步鎖的資源消耗,但是如果不用工廠時,也會建立對象佔用資源。
③雙重檢查加鎖方法:
//volatile編譯器使用處理多安全執行緒 private volatile static ChocolateFactory uniqeInstance=null ;//構造類對象 public static ChocolateFactory getInstance() { //是否為空白,同事調用時保持狀態不變 if(uniqeInstance==null){
//第一個線程執行到這裡,為空白.若第二個線程也到這裡,也要為空白,new對象,返回.二者只能一個進入
//擷取到一個對象,返回;另一個線程重新進入時,判斷不為空白,跳出(只要進入一次,就不會為空白了). synchronized (ChocolateFactory.class){ if(uniqeInstance==null){ uniqeInstance=new ChocolateFactory(); } } } return uniqeInstance; }
2.單例模式的分類
單例模式有很多表現形式,常見的有懶漢式,饑漢式,登記式
懶漢式:是指類保留的對象的建立時間是在需要時進行(用到時才建立);
饑漢式:和懶漢式相反,類保留的對象在第一次訪問時就建立了(和上面的"急切"建立法一致);
JAVA設計模式--單例模式