Java設計模式--單例模式

單例模式

單例定義:
Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。

在很多操作中,比如建立目錄 數據庫連接都需要這樣的單線程操作。

還有, singleton能夠被狀態化; 這樣,多個單態類在一起就可以作爲一個狀態倉庫一樣向外提供服務,比如,論壇中的帖子計數器,每次瀏覽一次需要計數,單態類能保持住這個計數,並且能synchronize的安全自動加1,如果你要把這個數字永久保存到數據庫,你可以在不修改單態接口的情況下方便的做到。

另外方面,Singleton也能夠被無狀態化。提供工具性質的功能,

Singleton模式就爲我們提供了這樣實現的可能。使用Singleton的好處還在於可以節省內存,因爲它限制了實例的個數,有利於Java垃圾回收(garbage collection)。

我們常常看到工廠模式中類裝入器(class loader)中也用Singleton模式實現的,因爲被裝入的類實際也屬於資源。

單例模式的特點:

單例類只能有一個實例。

單例類必須自己創建自己的唯一實例。

單例類必須給所有其他對象提供這一實例。

單例模式的幾種結構:

這裏主要寫餓漢式,懶漢式,雙重檢查,內部類,現在好像還有一種是用枚舉來實現,可以去了解一下哦!

1.餓漢式是典型的空間換時間,當類裝載的時候就會創建類的實例,不管你用不用,先創建出來,然後每次調用的時候,就不需要再判斷,節省了運行時間

public class Singleton {
  private Singleton(){}
  private static Singleton instance = new Singleton();
  //這裏提供了一個供外部訪問本class的靜態方法,可以直接訪問類被加載時,靜態變量instance會被初始化,此時類的私有構造子會被調用。裝載類的時候就創建對象實例
  public static Singleton getInstance() {
    return instance;   
   } 
}

2.懶漢式是典型的時間換空間,就是每次獲取實例都會進行判斷,看是否需要創建實例,浪費判斷的時間。當然,如果一直沒有人使用的話,那就不會創建實例,則節約內存空間。

public class Singleton {
  private static Singleton instance = null;
//對靜態工廠方法使用了同步化,以處理多線程環境
  public static synchronized Singleton getInstance() {

  if (instance==null)
    instance=new Singleton();
  return instance;   }

}
3. “雙重檢查加鎖”來實現:並不是每次進入getInstance方法都需要同步,而是先不同步,進入方法後,先檢查實例是否存在,如果不存在才進行下面的同步塊,這是第一重檢查,進入同步塊過後,再次檢查實例是否存在,如果不存在,就在同步的情況下創建一個實例,這是第二重檢查。這樣一來,就只需要同步一次了,從而減少了多次在同步情況下進行判斷所浪費的時間。

“雙重檢查加鎖”機制的實現會使用關鍵字volatile它的意思是:被volatile修飾的變量的值,將不會被本地線程緩存,所有對該變量的讀寫都是直接操作共享內存,從而確保多個線程能正確的處理該變量。

public class Singleton {
    private volatile static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        //先檢查實例是否存在,如果不存在才進入下面的同步塊
        if(instance == null){
            //同步塊,線程安全的創建實例
            synchronized (Singleton.class) {
                //再次檢查實例是否存在,如果不存在才真正的創建實例
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

4.一種可行的方式就是採用類級內部類,在這個類級內部類裏面去創建對象實例。這樣一來,只要不使用到這個類級內部類,那就不會創建對象實例,從而同時實現延遲加載和線程安全。
public class Singleton {
    
    private Singleton(){}
  
    private static class SingletonHolder{
          private static Singleton instance = new Singleton();
    }
    
    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}


當getInstance方法第一次被調用的時候,它第一次讀取SingletonHolder.instance,
導致SingletonHolder類得到初始化;而這個類在裝載並被初始化的時候,會初始化它的靜態域,
從而創建Singleton的實例,由於是靜態的域,因此只會在虛擬機裝載類的時候初始化一次,並由虛擬機來保證它的線程安全性。
這個模式的優勢在於,getInstance方法並沒有被同步,並且只是執行一個域的訪問,因此延遲初始化並沒有增加任何訪問成本。
發佈了43 篇原創文章 · 獲贊 15 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章