SingletonPattern單例模式

單例模式

1.定義

確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例java

餓漢式單例模式數據庫

public class Singleton {
    private static final Singleton singleton = new Singleton();

    // 構造器私有化,限制產生多個對象
    private Singleton() {}

    // 對外提供靜態方法獲取實例對象
    public static Singleton getInstence() {
      	return singleton;
    }
}

2.應用

2.1優勢

  • 因爲單例模式在內存中只有一個實例,減少了內存開支。特別在一個對象須要頻繁的建立銷燬時,建立銷燬時性能沒法優化,此時的優點很是明顯
  • 因爲單例模式只生成一個實例,減小了系統的性能開銷。當一個對象須要產生較多的資源時,如讀取配置,產生其它以來對象,能夠經過在應用啓動時直接產生一個單例對象,而後永久駐留內存的方式解決(JavaEE中採用單例模式時須要注意JVM的垃圾回收機制)
  • 單例模式能夠避免對同一資源的多重佔用,例如寫文件操做

2.2缺點

  • 單例模式通常沒有接口,擴展性差
  • 單例模式不利於測試。在並行開發環境中,若單例模式沒有完成,不能進行測試

2.3使用場景

  • 生成惟一序列號的環境
  • 在整個項目中須要一個共享訪問點或共享數據。如一個Web頁面上的計數器,使用單例模式保持計數器的值,並確保是線程安全的
  • 建立一個對象時須要消耗的資源過多,如訪問IO和數據庫等資源
  • 須要定義大量的靜態常量和靜態方法(如工具類)的環境

2.4注意事項

在該併發狀況下,須要注意單例模式的線程同步問題。單例模式有幾種不一樣的實現方式,餓漢式單例模式不會產生多實例的狀況,如下方式則須要考慮線程同步問題安全

懶漢式單例模式併發

public class Singleton {
    private static final Singleton singleton = null;

    // 構造器私有化,限制產生多個對象
    private Singleton() {}

    // 對外提供靜態方法獲取實例對象
    public static Singleton getInstence() {
        if (singleton == null) {
          singleton = new Singleton();
        }
      
        return singleton;
    }
}

懶漢式單例模式在低併發狀況下尚不會出現問題,若系統壓力增大,併發量增長時可能在內存中存在多個實例。如一個線程A執行到singleton = new Singleton();但尚未得到到對象,此時對象初始化未完成,第二個線程B執行到if (singleton == null) {那麼線程B判斷條件也爲true,因而繼續執行下去,則A和B各得到一個對象。dom

解決單例模式線程不安全的方法,能夠在getInstence方法前或方法內加synchronized關鍵字來實現,建議採用餓漢式單例模式。工具

3.擴展

有上限的多例模式:產生固定數量對象的模式性能

public class Singleton {
    // 定義最多能產生的實例數量
    private static int maxNumOfInstance = 2;

    // 定義一個列表容納全部實例
    private static List<Singleton> singletonList = new ArrayList<>();

    // 定義當前對象實例的序號
    private static int countNumOfInstance = 0;

    // 產生全部的對象
    static {
        for (int i = 0; i < maxNumOfInstance; i++) {
            singletonList.add(new Singleton())
        }
    }

    private Singleton() {}

    public static Singleton getInstence() {
      	Random random = new Random();
      	countNumOfInstance = random.nextInt(maxNumOfInstance);

      	return singletonList.get(countNumOfInstance);
    }
}

考慮到線程安全問題可使用Vector來代替。採用有上限的多例模式,能夠在設計時決定內存中有多少個實例,方便系統擴展,修正單例可能存在的性能問題,提升系統的響應速度。如讀取文件,能夠在系統啓動時完成初始化工做,在內存中啓動固定數量的Reader實例。測試

相關文章
相關標籤/搜索