Java中單例模式之餓漢式和懶漢式
阿新 • • 發佈:2019-02-12
單例模式顧名思義,就是隻能建立一個物件,這裡就限制了它的構造方法,不能隨便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