概念:
Java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,這裏主要介紹兩種:懶漢式單例、餓漢式單例。
單例模式有如下特色:
一、單例類只能有一個實例。
二、單例類必須本身建立本身的惟一實例。
三、單例類必須給全部其餘對象提供這一實例。
單例模式確保某個類只有一個實例,並且自行實例化並向整個系統提供這個實例。在計算機系統中,線程池、緩存、日誌對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。這些應用都或多或少具備資源管理器的功能。每臺計算機能夠有若干個打印機,但只能有一個Printer Spooler,以免兩個打印做業同時輸出到打印機中。每臺計算機能夠有若干通訊端口,系統應當集中管理這些通訊端口,以免一個通訊端口同時被兩個請求同時調用。總之,選擇單例模式就是爲了不不一致狀態,避免政出多頭。設計模式
1、懶漢式單例緩存
//懶漢式單例類.在第一次調用的時候實例化本身 public class Singleton { private Singleton() {} private static Singleton single =null; //靜態工廠方法 public static Singleton getInstance() { if (single == null) { single = new Singleton(); return single; } } }
Singleton經過將構造方法限定爲private避免了類在外部被實例化,在同一個虛擬機範圍內,Singleton的惟一實例只能經過getInstance()方法訪問。
(事實上,經過Java反射機制是可以實例化構造方法爲private的類的,那基本上會使全部的Java單例實現失效。此問題在此處不作討論,姑且掩耳盜鈴地認爲反射機制不存在。)安全
可是以上懶漢式單例的實現沒有考慮線程安全問題,它是線程不安全的,併發環境下極可能出現多個Singleton實例,要實現線程安全,有如下三種方式,都是對getInstance這個方法改造,保證了懶漢式單例的線程安全,若是你第一次接觸單例模式,對線程安全不是很瞭解,能夠先跳過下面這三小條,去看餓漢式單例,等看完後面再回頭考慮線程安全的問題:多線程
一、在getInstance方法上加同步併發
public static synchronized Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; }
★二、雙重檢查鎖定性能
public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) //靜態方法中同步代碼塊的鎖是字節碼文件,即所在類的文件 { if (singleton == null) { singleton = new Singleton(); } } } return singleton; }
三、靜態內部類線程
public class Singleton { private static class LazyHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return LazyHolder.INSTANCE; } }
這種比上面一、2都好一些,既實現了線程安全,又避免了同步帶來的性能影響。設計
2、餓漢式單例日誌
//餓漢式單例類.在類初始化時,已經自行實例化 public class Singleton { private Singleton() {} private static final Singleton single = new Singleton(); //靜態工廠方法 public static Singleton getInstance() { return single; } }
餓漢式在類建立的同時就已經建立好一個靜態的對象供系統使用,之後再也不改變,因此天生是線程安全的。code
餓漢式和懶漢式區別
從名字上來講,餓漢和懶漢,
餓漢就是類一旦加載,就把單例初始化完成,保證getInstance的時候,單例是已經存在的了,
而懶漢比較懶,只有當調用getInstance的時候,纔回去初始化這個單例。
另外從如下再區分如下這兩種方式:
線程安全:
餓漢式天生就是線程安全的,能夠直接用於多線程而不會出現問題,
懶漢式自己是非線程安全的,爲了實現線程安全有幾種寫法,分別是上面的一、二、3,這三種實如今資源加載和性能方面有些區別。