夕阳下, 那是我在奔跑——单件模式

747 查看

單件模式(JAVA實現)

定義

單件模式: 確保一個類只有一個實列, 並提供一個全局訪問點

單件模式和全局變量的區別

若將對象賦值給一個全局變量, 則該對象需在程序開始時就創建好, 而改對象可能不會使用, 造成資源浪費, 而單件模式支持延遲實例化

即急切實例化 和 延遲實例化 的區別

類圖:

單件模式

1 基本用法(懒汉式)


class Singleton
{
    private static Singleton singleton;
    private Singleton(){};
    public static Singleton getInstance()
    {
        if (null == singleton) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

以上爲單列模式的懒汉式設計

該設計時線程不安全的, 即當不同的線程調用getInstance時, 返回不同的對象。

2 急切的創建對象(饿汉式)

class Singleton
{
    private static Singleton singleton = new Singleton();
    private Singleton(){};
    public static Singleton getInstance()
    {
        return singleton;
    }
}

以上爲饿汉式單列設計, 該設計是線程安全的, 即不同的線程在調用getInstance時返回的是統一對象,

JVM在加載這個類時, 馬上創建了這個類的唯一單列實列。

同步 synchronized

其實, 只要把getInstance變成同步的, 就能解決懒汉式線程不安全這一不足,

設計如下:

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

以上爲加鎖了的懒汉式單列設計, 該設計是線程安全的, 不同的線程在調用getInstance時, 返回唯一對象,

但是, 後續每一次調用getinstance時,都會進入同步鎖, 同步會降低性能, 這是真的, 尤其是當該類用於很多業務邏輯時,

雙重檢查加鎖

用雙重檢查加鎖, 在getInstance中減少使用同步

class Singleton
{
    private volatile static Singleton singleton;
    private Singleton(){};
    public static Singleton getInstance()
    {
        if (null == singleton) {
            synchronizend(Singleton.class) {
                if (null == singleton) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

需java版本>=1.5, 地版本不支持volatile關鍵字

以上即爲雙重檢查加鎖, 該設計能大大的減少getInstance的性能消耗,

準備是用php來實現的, 但是發現php暫不支持同步代碼快, 此處採用java實現了

轉載請著名出處,godruoyi