1、什麼是單例模式?
一、定義
Singleton模式要求一個類有且僅有一個實例,而且提供了一個全局的訪問點。這就提出了一個問題:如何繞過常規的構造器,提供一種機制來保證一個類只有一個實例?客戶程序在調用某一個類時,它是不會考慮這個類是否只能有一個實例等問題的,因此,這應該是類設計者的責任,而不是類使用者的責任。java
<!--more-->數據庫
從另外一個角度來講,Singleton模式其實也是一種職責型模式。由於咱們建立了一個對象,這個對象扮演了獨一無二的角色,在這個單獨的對象實例中,它集中了它所屬類的全部權力,同時它也肩負了行使這種權力的職責安全
二、單例模式的優勢
1)在單例模式中,活動的單例只有一個實例,對單例類的全部實例化獲得的都是相同的一個實例。這樣就 防止其它對象對本身的實例化,確保全部的對象都訪問一個實例工具
2)單例模式具備必定的伸縮性,類本身來控制實例化進程,類就在改變實例化進程上有相應的伸縮性。性能
3)提供了對惟一實例的受控訪問。spa
4)因爲在系統內存中只存在一個對象,所以能夠 節約系統資源,當 須要頻繁建立和銷燬的對象時單例模式 無疑能夠提升系統的性能。線程
5)容許可變數目的實例。設計
6)避免對共享資源的多重佔用。日誌
三、單例模式的應用場景
單例模式只容許建立一個對象,所以節省內存,加快對象訪問速度,所以對象須要被公用的場合適合使用,如多個模塊使用同一個數據源鏈接對象等等。如:code
1)須要頻繁實例化而後銷燬的對象。
2)建立對象時耗時過多或者耗資源過多,但又常常用到的對象。
3)有狀態的工具類對象。
4)頻繁訪問數據庫或文件的對象。
如下都是單例模式的經典使用場景:
1)資源共享的狀況下,避免因爲資源操做時致使的性能或損耗等。如上述中的日誌文件,應用配置。
2)控制資源的狀況下,方便資源之間的互相通訊。如線程池等
2、單例的四種實現方式
一、餓漢式
餓漢式: 在類裝載的時候就急速的初始化,餓漢式是線程安全的、 可是沒有延遲加載
/** * 餓漢式 */ class Singleton_one { // 一、私有化構造器 private Singleton_one() { } // 二、初始化 private static Singleton_one instance = new Singleton_one(); public static Singleton_one getInstance() { return instance; } }
二、懶漢式(同步方法)
單純的懶漢式是存在線程安全問題的、須要咱們使用同步策略
/** * 懶漢式(同步方法) */ class Singleton_two { // 一、私有化構造器 private Singleton_two() { } private static Singleton_two instance = null; public synchronized static Singleton_two getInstance() { if (instance == null) { instance = new Singleton_two(); } return instance; } }
三、懶漢式(Dubbo Check)
單純的懶漢式是存在線程安全問題的、須要咱們使用同步策略、這裏使用了雙重校驗
/** * 懶漢式(Double Check) */ class Singleton_three { // 私有化構造器 private Singleton_three() { } private static Singleton_three instance = null; public static Singleton_three getInstance() { if (instance == null) { synchronized (Singleton_three.class) { if (instance == null) { instance = new Singleton_three(); } } } return instance; } }
四、靜態內部類
1)靜態內部類的加載時機
- 外部類初次加載,會初始化靜態變量、靜態代碼塊、靜態方法,但不會加載內部類和靜態內部類。
- 實例化外部類,調用外部類的靜態方法、靜態變量,則外部類必須先進行加載,但只加載一次。
- 直接調用靜態內部類時,外部類不會加載。
/** * 內部類實現單例模式 * <p> * 既不用加鎖 、也能實現懶加載 * * * 外部類初次加載的時候不會加載內部類和靜態內部類 */ class Singleton_four { private static int a = 10; // 私有化構造器 private Singleton_four() { } private static class Inner { static Singleton_four instance = new Singleton_four(); } public static Singleton_four getInstance() { return Inner.instance; } }