1. 程式人生 > 程式設計 >一文帶你瞭解單例設計模式

一文帶你瞭解單例設計模式

1.基本介紹

單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。

這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。

2.實現方式

通常單例模式在Java語言中,有兩種構建方式:

  • 懶漢式—執行緒不安全:最基礎的實現方式,執行緒上下文單例,不需要共享給所有執行緒,也不需要加synchronize之類的鎖,以提高效能。
  • 懶漢式—執行緒安全:加上synchronize之類保證執行緒安全的基礎上的懶漢模式,相對效能很低,大部分時間並不需要同步
  • 餓漢方式。指全域性的單例例項在類裝載時構建。 [2]
  • 雙檢鎖式。在懶漢式基礎上利用synchronize關鍵字和volatile關鍵字確保第一次建立時沒有執行緒間競爭而產生多個例項,僅第一次建立時同步,效能相對較高
  • 登記式。作為建立類的全域性屬性存在,建立類被裝載時建立
  • 列舉。java中列舉類本身也是一種單例模式

K1VK78.png

三大要素:

  • 私有的構造方法;
  • 指向自己例項的私有靜態引用;
  • 以自己例項為返回值的靜態的公有方法。

3.相關例項

①餓漢式單例(執行緒安全)

闡述:見名知義,“餓漢”說明它很“飢餓”,迫切需要找到吃的,這裡也就是我們所說的例項。為什麼說它是執行緒安全的呢?因為我們一開始就建立一個這樣的例項,其他執行緒在訪問前這個例項就已經建立完成,在類的生命週期中只建立一次,所以餓漢單例天生就是執行緒安全的。

// 餓漢式單例示例
class Singletone {

    private static  Singletone singleton = new Singletone();

    // 懶漢式
    private Singletone() {

    }

    // 保證返回一個例項
    public static Singletone getSingleton() {
        return singleton;
    }

}


public class EHanShi {

    public static void main(String[] args) 
{ Singletone singleton1 = Singletone.getSingleton(); Singletone singleton2 = Singletone.getSingleton(); System.out.println(singleton1==singleton2); } } 複製程式碼

輸出結果為: true

②懶漢單例(需要加雙重檢查鎖來保證執行緒安全)

闡述: 所謂懶漢模式,就是像一個“懶漢”一樣,需要用到建立例項了程式再去建立例項,不需要建立例項程式就“懶得”去建立例項。為什麼說它不是執行緒安全的呢?因為在高併發的情況下懶漢單例就可能建立多個,這樣不僅違背了單例的原則,也會在造成使用不同例項造成的執行緒安全問題,所以懶漢單例需要加鎖。

// 懶漢單例 執行緒不安全 需要雙重檢查鎖保證在JVM中只能有一個例項
class Singleton {

    // 使用volatile禁止指令重排序
    private static volatile Singleton singleton;

    // 懶漢式
    private Singleton() {

    }

    // 保證返回一個例項
    public static Singleton getSingleton() {
        if (singleton == null) {  // 第一層鎖
            synchronized (Singleton.class) {
                if (singleton == null) { //第二層鎖
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

}

public class LanHanShi {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getSingleton();
        Singleton s2 = Singleton.getSingleton();
        System.out.println(s1 == s2);

    }

}
複製程式碼

輸出結果為: true

4.總結

懶漢式和餓漢式區別點:

  • 餓漢模式是典型的空間換取時間,當類裝載的時候就會建立類的例項,不管你用不用,先創建出來,然後每次呼叫的時候就不需要再判斷了,節省了執行時間。但如果一直沒有人呼叫,這種浪費的空間就不值得,特別是在空間不足的情況下。

  • 懶漢模式是這是一種時間換空間的做法,要想執行緒安全,大家第一想到的便是下面這種方式,就是在getSingleton方法加上synchronized關鍵字,但是這種方式也有致命的缺點,那就是併發率太低。