单例模式的5种实现方法及优缺点
單例模式是GoF23種設計模式中創建型模式的一種,也是所有設計模式中最簡單的一種。
單例模式是用來保證系統中某個資源或對象全局唯一的一種模式,比如系統的線程池、日志收集器等。它保證了資源在系統中只有一份,一方面節省資源,另一方面可以避免并發時的內存安全問題。
餓漢模式
public class Singleton { ?private static final Singleton INSTANCE = new Singleton(); ?private Singleton() {} ?public static Singleton getInstance() {return INSTANCE;} }餓漢模式是在類加載的時候直接創建了對象,不存在線程安全問題,它的優點是簡單方便,缺點是如果這個類在不需要創建單例對象的時候就會裝載(比如這個類有其它靜態方法被調用)的話,會造成浪費,不過只要遵循單一職責原則,一般不會有這種問題。
所以只要不存在奇怪情況,推薦用餓漢模式。
懶漢模式
public class Singleton { ?private static Singleton INSTANCE; ?private Singleton() {} ?public static Singleton getInstance() {if (INSTANCE == null) {INSTANCE = new Singleton();}return INSTANCE;} }與餓漢模式相比,變量定義上的final被去掉,getInstance()方法中增加了一次null判斷,很顯然,有線程安全問題,與餓漢模式相比,懶漢模式可以在實例化過程中通過外部傳遞參數的形式控制實例化對象。
寧愿用餓漢模式也不要用懶漢模式,不推薦使用。
雙重鎖懶漢模式
public class Singleton { ?private volatile static Singleton INSTANCE; ?private Singleton() {} ?public static Singleton getInstance() {if (INSTANCE == null) {synchronized (Singleton.class) {if (INSTANCE == null) {INSTANCE = new Singleton();}}}return INSTANCE;} }與上面的懶漢模式相比,變量定義上增加了volatile避免指令問題,getInstance()方法中有加了鎖,里面又加了一次null判斷,防止兩個線程同時執行getInstance()且兩個線程第一個null都判斷通過,但一個線程還沒拿鎖就被另一個線程先拿了鎖之后重復創建對象的情況。
與餓漢模式相比,幾乎適用于所有情況,但復雜度上升。
如果需要兼顧大多數的情況,可以使用雙重鎖懶漢模式。
靜態內部類模式
public class Singleton { ?private Singleton() {} ?private static class SingletonInnerClass{private static Singleton INSTANCE = new Singleton();} ?public static Singleton getInstance() {return SingletonInnerClass.INSTANCE;} }與餓漢模式相比,實例定義屬性放到了內部類中,Singleton類加載后并不會立即加載內部類,只有第一次調用getInstance()方法后,內部類才會被加載,不存在線程安全問題,比餓漢模式適應了更多的情況,復雜度比雙重鎖懶漢模式低,和餓漢模式一樣,外部無法控制實例初始化的過程,無法傳遞參數進去。
如果單例類需要在脫離單例對象的情況下使用,可以用靜態內部類模式。
類只能同時被1個線程初始化,且在同一個加載器中,同一個類不會第二次初始化。所以餓漢模式和靜態內部類模式都沒有線程安全問題
枚舉單例模式
public enum Singleton { ?INSTANCE; ?private String field1;private Integer field2; ?public void method1(){// ...} ?public void method2(){// ...} }在java中,enum可以像一個正常的class一樣定義屬性和方法,可以實現接口,但不能繼承。
雖然它不復雜,且無法通過反射搞破壞,但它無法適用于更廣泛的情況。
如果單例模式可能被破壞,可以使用枚舉單例模式。
總結
上面5種方式中,比較推薦餓漢模式,它雖然可能有資源浪費,但這個可能性真的很小,最重要的是它實現起來非常簡單。
?
總結
以上是生活随笔為你收集整理的单例模式的5种实现方法及优缺点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RocketMQ 消息持久化机制
- 下一篇: TransactionTemplate和