1. 程式人生 > 其它 >單例模式-設計模式

單例模式-設計模式

技術標籤:設計模式

動機

  1. 在軟體系統中,經常有這樣一些特殊的類,必須保證它們在系統中只存在一個例項,才能確保它們的邏輯正確性、以及良好的效率。
  2. 如何繞過常規的構造器,提供一種機制來保證一個類只要一個例項?
  3. 這應該是類設計者的責任,而不是使用者的責任。

模式定義

保證一個類僅有一個例項,並提供一個該例項的全域性訪問點。

類圖

在這裡插入圖片描述

總結

  1. Singleton模式中的例項構造器可以設定為protected已允許子類派生。
  2. Singleton模式一般不要支援拷貝建構函式和Clone介面,因為這有可能導致多個物件例項,與Singleton模式的初衷違背。
  3. 如何實現多執行緒環境下安全的Singleton?注意對雙檢查鎖的正確實現。

例項

注意點

  • 單例模式需要把建構函式設定為虛擬函式
  • 需要考慮多執行緒的問題
  • 使用雙檢查鎖機制
  • 防止指令重排,java中使用volatile關鍵字
  1. 單列類
public class HouseSingleton {
    // 新增volatile是為了避免指令重排
    private static volatile HouseSingleton houseSingleton = null;

    private HouseSingleton() {
        System.out.println("Create HouseSingleton");
    }

    public
static HouseSingleton getInstance() { // 雙檢查鎖機制,可以保證只有例項每建立的時候鎖一次,其他情況下都不會鎖執行緒,不會導致效能下降。 // 問題是,可能出現指令重排,先分配記憶體然後直接把記憶體地址賦值給引用變數,導致還沒執行建構函式; // 因此部分執行緒不能正常使用例項,因此需要藉助volatile關鍵字避免指令重排。 if (houseSingleton == null) { synchronized (HouseSingleton.class) { if
(houseSingleton == null) { houseSingleton = new HouseSingleton(); return houseSingleton; } } } return houseSingleton; } public void say() { System.out.println("Say hello, name:" + Thread.currentThread().getName()); } }
  1. 多執行緒呼叫單例類
public class Client {
    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(() -> {
                HouseSingleton houseSingleton = HouseSingleton.getInstance();
                houseSingleton.say();
            }, "thread" + (i + 1));

            thread.start();
        }

        Thread.sleep(10000);

    }
}
// 執行結果
Create HouseSingleton
Say hello, name:thread1
Say hello, name:thread2
Say hello, name:thread3
Say hello, name:thread4
Say hello, name:thread86
Say hello, name:thread6
Say hello, name:thread7
Say hello, name:thread8
Say hello, name:thread9
Say hello, name:thread10
Say hello, name:thread11
Say hello, name:thread12
Say hello, name:thread13
Say hello, name:thread14
Say hello, name:thread15
Say hello, name:thread16
Say hello, name:thread18
Say hello, name:thread17
Say hello, name:thread19
Say hello, name:thread20
Say hello, name:thread21
Say hello, name:thread22
Say hello, name:thread23
Say hello, name:thread24
Say hello, name:thread25
Say hello, name:thread26
Say hello, name:thread27
Say hello, name:thread28
Say hello, name:thread29
Say hello, name:thread30
Say hello, name:thread31
Say hello, name:thread32
Say hello, name:thread33
Say hello, name:thread34
Say hello, name:thread35
Say hello, name:thread36
Say hello, name:thread38
Say hello, name:thread39
Say hello, name:thread40
Say hello, name:thread41
Say hello, name:thread42
Say hello, name:thread43
Say hello, name:thread44
Say hello, name:thread99
Say hello, name:thread97
Say hello, name:thread95
Say hello, name:thread100
Say hello, name:thread92
Say hello, name:thread91
Say hello, name:thread37
Say hello, name:thread90
Say hello, name:thread85
Say hello, name:thread84
Say hello, name:thread83
Say hello, name:thread81
Say hello, name:thread79
Say hello, name:thread77
Say hello, name:thread87
Say hello, name:thread76
Say hello, name:thread78
Say hello, name:thread89
Say hello, name:thread74
Say hello, name:thread73
Say hello, name:thread67
Say hello, name:thread65
Say hello, name:thread94
Say hello, name:thread96
Say hello, name:thread64
Say hello, name:thread63
Say hello, name:thread98
Say hello, name:thread62
Say hello, name:thread61
Say hello, name:thread66
Say hello, name:thread60
Say hello, name:thread58
Say hello, name:thread68
Say hello, name:thread56
Say hello, name:thread55
Say hello, name:thread54
Say hello, name:thread52
Say hello, name:thread69
Say hello, name:thread70
Say hello, name:thread71
Say hello, name:thread72
Say hello, name:thread75
Say hello, name:thread80
Say hello, name:thread82
Say hello, name:thread5
Say hello, name:thread88
Say hello, name:thread46
Say hello, name:thread50
Say hello, name:thread45
Say hello, name:thread93
Say hello, name:thread49
Say hello, name:thread48
Say hello, name:thread47
Say hello, name:thread51
Say hello, name:thread53
Say hello, name:thread57
Say hello, name:thread59