單例模式總結

2021-09-26 18:22:00 字數 1479 閱讀 1311

單例模式,最常見的有兩種單例模式,餓漢式和懶漢式,如下:

/**

* 餓漢式

*/public class singletonhungry

public singletonhungry getinstance()

}

/**

*懶漢式

*/public class singletonlazy

//靜態工廠方法

public static singletonlazy getinstance()

return instance;

}}

上述兩種方式都存在著執行緒不安全的情況,以懶漢式為例,instance物件還沒建立的時候,如果兩條執行緒訪問getinstance方法,進入了if條件,同時都new的話,就產生了兩個例項。

解決方案:synchronized加雙重檢測

/**

*synchronized加雙重檢測

*/public class singletonsyn

//靜態工廠方法

public static singletonsyn getinstance()}}

return instance;

}}

解析:雙重檢測的好處,就是首先判斷instance為空,有兩條執行緒都可以進入了這判斷條件,當一條執行緒執行完了getinstance方法,釋放了鎖, 然後另一條執行緒已經進入第一層判斷,這時可獲取鎖,如果在synchronized**塊不做判斷就有產生了乙個例項,就不是單例了

存在問題:此時仍難不是執行緒安全的,因為jvm會進行指令重排,new乙個物件的步驟是1.分配物件的記憶體空間2.初始化物件3.設定instance指向剛分配的例項 *有些時候jvm會把其順序條為1,3,2,3過程執行了物件就不等於null,所以就存在下邊這種情況,執行緒a在new物件,執行緒b在第乙個條件判斷 * 當執行緒a先執行了1,3,此時執行緒b剛好判斷為false,那麼執行緒b直接返回instance,這是乙個沒建立好的物件,所以就出錯了

解決方案:單例加上volatile關鍵字防止指令重排

/**

*執行緒安全的單例**

*/public class singletonsyn

//靜態工廠方法

public static singletonsyn getinstance()}}

return instance;

}}

存在問題:此時還會存在乙個問題,我們能利用反射仍可獲得多個物件

解決辦法:用列舉類

/**

* 列舉類實現單例模式

*/public enum singletonenum

public void print()

}public static void main(string args)

至此單例一些情況全都介紹完了

單例模式總結

三種實現單例模式的對比 1.volatile關鍵字不但可以防止指令重排,也可以保證執行緒訪問的變數值是 主記憶體中的最新值 有關volatile的詳細原理,我在以後的漫畫中會專門講解。2.使用列舉實現的單例模式,不但可以防止利用反射強行構建單例物件 可以而且在列舉類物件被 反序列化 的時候,保證反序...

單例模式總結

單例模式的使用有乙個必要的條件,在乙個系統要求乙個類只有乙個例項時才應當使用單例模式。在懶漢式單例的時候為什麼要進行執行緒的控制呢?package 單例模式.懶漢模式 public class lazysingleton synchronized public lazysingleton getin...

單例模式總結

一 單例模式 singleton pattern 單例模式只涉及到乙個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。並且提供了訪問其唯一物件的方式,可以直接訪問,不需要在外部例項化該類的物件。1 單例模式可總結為以下三點 1 構造方法使用private私有化 保證外部無法new出例項...