1. 程式人生 > >Java中單例模式之餓漢式和懶漢式

Java中單例模式之餓漢式和懶漢式

單例模式顧名思義,就是隻能建立一個物件,這裡就限制了它的構造方法,不能隨便new了。所以用構造方法用private修飾。

餓漢式和懶漢式通過名字也是可以區分的。

餓漢式,餓了就主動去找食物了,就直接主動建立一個物件。然後通過公共的方法暴露給外部呼叫。

懶漢式,懶了就用的時候再去建立物件,所以原來設定個空的。需要用的時候,先檢查有沒有物件,如果沒有,就呼叫公共的方法來new一個物件出來。下面是二者的程式碼。可以做一下對比。

餓漢式

public class Singleton {
	private Singleton () {}
	private static Singleton instance=new Signleton();
	public static  Singleton getInstance() {
		
		return instance;
	}	

}

懶漢式

public class Singleton {
    private Sigleton() {}
    private static Singleton instance=null;
    public static  Singleton getInstance() {
        if(instance==null) {
            instance=new Singleton();
        }
        return instance;
    }    
}

二者的實質區別:

懶漢式是現成不安全的,因為假設Singleton類剛剛被初始化,instance物件還是空,這時候兩個執行緒同時訪問getInstance,可能就會new兩次。就不是單例模式了。

修改程式碼如下。

public class Singleton {
    private Singleton() {}  //私有建構函式
   private static Singleton instance = null;  //單例物件
   //靜態工廠方法
   public static Singleton getInstance() {
        if (instance == null) {      //雙重檢測機制
         synchronized (Singleton.class){  //同步鎖
           if (instance == null) {     //雙重檢測機制
             instance = new Singleton();
               }
            }
         }
        return instance;
    }
}

為了防止new Singleton被執行多次,因此在new操作之前加上Synchronized 同步鎖,鎖住整個類(注意,這裡不能使用物件鎖)。

進入Synchronized 臨界區以後,還要再做一次判空。因為當兩個執行緒同時訪問的時候,執行緒A構建完物件,執行緒B也已經通過了最初的判空驗證,不做第二次判空的話,執行緒B還是會再次構建instance物件。

以上其實也不是絕對的安全的。再修改可以用volatile關鍵字來修改,或者用列舉。這裡自己學的不是很深,參考漫畫吧。連結如下。https://zhuanlan.zhihu.com/p/33102022