Java學習升階 -02-單例模式設計分析

單例模式定義

單例模式(Singleton),也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。

單例模式的作用

許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行爲方便管理,也使系統資源佔用率大大降低,也可以提高公共資源載入速度。

應用場景

比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然後服務進程中的其他對象再通過這個單例對象獲取這些配置信息。這種方式簡化了在複雜環境下的配置管理。需要頻繁的進行創建和銷燬的對象;創建對象時耗時過多或耗費資源過多,但又經常用到的對象;頻繁訪問數據庫或文件的對象。那麼可以初步歸納一下應用場景:

  • 公用靜態資源類
    如前端中模版頁、圖片鏈接等等
  • 全局信息類
    全局計數、環境變量、系統基本配置等
  • 無狀態工具類
    日誌工具、字符串工具、文件處理、圖片上傳等

單例模式的實現方法

Java學習升階 -02-單例模式設計分析

餓漢式

public class Singleton {

private final static Singleton INSTANCE = new Singleton();

private Singleton(){}

public static Singleton getInstance(){
    return INSTANCE;
}

}

同靜態代碼塊方式:

public class Singleton {

private static Singleton instance;

static {
    instance = new Singleton();
}

private Singleton() {}

public static Singleton getInstance() {
    return instance;
}

}

因爲餓漢模式是靜態變量實例化,在類加載時候就會完成實例化,所有優勢和劣勢都比較明顯:
1.線程安全
2.在類加載的同時已經創建好一個靜態對象,調用時反應速度快
缺點:資源效率不高,可能getInstance()永遠不會執行到,但執行該類的其他靜態方法或者加載了該類(class.forName),那麼這個實例仍然初始化

懶漢式

//懶漢式單例類.在第一次調用的時候實例化自己
public class Singleton {
private Singleton() {}
private static Singleton single=null;
//靜態工廠方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}

這種寫法起到了Lazy Loading的效果,但是只能在單線程下使用。如果在多線程下,一個線程進入了if (singleton == null)判斷語句塊,還未來得及往下執行,另一個線程也通過了這個判斷語句,這時便會產生多個實例。所以在多線程環境下不可使用這種方式。

改進01

public class Singleton {

private static Singleton singleton;

private Singleton() {}

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

}

解決上面第三種實現方式的線程不安全問題,做個線程同步就可以了,於是就對getInstance()方法進行了線程同步。缺點:效率太低了,每個線程在想獲得類的實例時候,執行getInstance()方法都要進行同步。而其實這個方法只執行一次實例化代碼就夠了,後面的想獲得該類實例,直接return就行了。方法進行同步效率太低要改進。
改進02-雙重檢查模式

public class Singleton {

private static volatile Singleton singleton;

private Singleton() {}

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

}

靜態內部類方式

public class Singleton {

private Singleton() {}

private static class SingletonInstance {
    private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
    return SingletonInstance.INSTANCE;
}

}

該方式在Singleton類被裝載時並不會立即實例化,而是在需要實例化時,調用getInstance方法,纔會裝載SingletonInstance類,從而完成Singleton的實例化。類的靜態屬性只會在第一次加載類的時候初始化,所以在這裏,JVM幫助我們保證了線程的安全性,在類進行初始化時,別的線程是無法進入的。
優點:避免了線程不安全,延遲加載,效率高。

枚舉式

public enum Singleton {
INSTANCE;
public void whateverMethod() {

}

}

藉助JDK1.5中添加的枚舉來實現單例模式。不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象。

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