設計模式5——單例模式

如果餓了就喫,困了就睡,渴了就喝,人生就太無趣了


1.定義

1.1 概念

確保一個類只有一個實例,並提供一個全局訪問點。簡單來說:將構造器私有化,並在靜態方法中初始化該類的靜態變量。

1.2 類圖

如圖1,定義一個該類的私有靜態變量uniqueInstance,並將構造器定義爲private(在圖中沒有顯示),通過靜態方法getInstance()uniqueInstance初始化並返回該實例。

在這裏插入圖片描述

2.單例模式各種類型。

2.1 經典類型

在使用時會被創建,但是在併發模式中會出現問題。

public class Singleton {
    private static Singleton uniqueInstance;

    private Singleton(){}

    public static Singleton getInstance(){
        if(uniqueInstance==null){
            uniqueInstance=new Singleton();
        }
        return uniqueInstance;
    }
}

2.2 同步鎖類型

getInstance變成同步方法。在方法聲明中加入 synchronized關鍵字。

synchronized:讓每個線程進入該關鍵字修飾的方法前,要先等待其他線程離開後才能訪問。


問題:這樣每次訪問getInstance()都會需要同步,但實際上只要uniqueInstance被設置好後就不需要同步,只是第一次訪問需要同步。如果程序需要大量訪問getInstance()方法,就會大大降低性能。

public class Singleton {
    private static Singleton uniqueInstance;

    // other useful instance variables here

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }

}

2.3 急切類型

uniqueInstance變量初始化交給靜態初始化器。JVM將保證線程安全,因爲JVM在加載這個類時會馬上創建一個唯一的單間實例,JVM保證任何線程訪問uniqueInstance前,一定會先創建此實例。

public class Singleton {
    private volatile static Singleton uniqueInstance=new Singleton();
    private Singleton() {}

    public static Singleton getInstance(){
        return uniqueInstance;
    }
}

2.4 雙重檢查加鎖類型

使用雙重檢查加鎖(double-checked locking),首先檢查實例是否已經創建了,如果尚未創建,再進行同步。這樣就只有第一次纔會同步。

volatile:

  • 類型修飾符。
  • 保證了不同線程對這個變量進行操作時的可見性。例如果對變量值進行改變,對其他線程是立即可見。(實現可見性)
  • 禁止進行指令重排序(實現有序性)
  • 保證對單次讀/寫的原子性。i++ 這種操作不能保證原子性。

這樣就確保了uniqueInstance被初始化時,多個線程能正確處理uniqueInstance變量。

  1. getInstance()方法中的第一個if保證在uniqueInstance初始化後,避免同步。
  2. getInstance()方法中的第二個if保證在線程a,b同時進入後,能夠有序執行同步鎖中的內容。沒有第二個if也是不能保證單例的。
public class Singleton {
    private volatile static Singleton uniqueInstance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

2.5 其他類型

沒有搞定,也就不敢亂寫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章