單例模式: 保證一個類只有一個實例,並且提供一個訪問該實例的全局訪問入口 1.Windows的任務管理器2.Windows的回收站,也是一個單例應用3.項目中的讀取配置文件的對象4.資料庫的連接池5.Servlet中的Application Servlet6.Spring中的Bean預設也是單例的7 ...
單例模式:
作用
保證一個類只有一個實例,並且提供一個訪問該實例的全局訪問入口
單例模式的常用
1.Windows的任務管理器
2.Windows的回收站,也是一個單例應用
3.項目中的讀取配置文件的對象
4.資料庫的連接池
5.Servlet中的Application Servlet
6.Spring中的Bean預設也是單例的
7.SpringMVC Struts中的控制器
單例模式的優點
1.由於單例模式只生成一個實例,減少了系統給的性能開銷,當一個對象需要產生時,當時消耗的資源較多。那麼產生對象時構建的方式就可以通過單例去構建。
2.單例模式存在全局訪問點,所以可以優化共用資源訪問。
常見的單例模式的構建方法:
1.餓漢式:線程安全 調用率高 但是不能延遲載入
2.懶漢式:線程安全 調用率不高 但是可以延遲載入
3.雙重檢測(double check )
4.靜態內部類(線程安全 可以延遲載入)
5.枚舉單例 線程安全 不可以延遲載入
代碼案例展示
餓漢式
/** * 餓漢式: * 類只要被載入就會被載入全局變數,所以餓漢式,會被及時載入。(沒有懶載入 ) * 並且存在天然的線程安全問題。 * @author 碼歌老薛 * @date 創建時間 猴年馬月 * @version 1.0 */ public class SingleHungry { //提供靜態的全局變數 作為訪問該類實例的入口 private static SingleHungry sh = new SingleHungry(); /** * 構造器私有 無法創建對象 */ private SingleHungry(){ } /** * 對外提供get方法獲取 該類的實例 * @return */ public static SingleHungry getInstance(){ return sh; } }
懶漢式
/** * 懶漢式: * 全局變數初始化放到了實例化方法中,延遲產生對象。 * 但是當多個線程統一訪問時,有可能出現線程不安全的情況。需要優化。 * @author 碼歌老薛 * @date 創建時間 猴年馬月 * @version 1.0 */ public class SingleLazy implements Serializable{ //提供靜態的全局變數 作為訪問該類實例的入口 但是這裡不立即載入 private static SingleLazy sh = null; /** * 構造器私有 無法創建對象 */ private SingleLazy(){ System.out.println("構造函數被調用了"); } /** * 對外提供get方法獲取 該類的實例 * @return * @throws InterruptedException */ public static synchronized SingleLazy getInstance() { if(sh==null){ sh = new SingleLazy(); } return sh; } }
上海尚學堂java培訓 shsxt.com
雙重檢測
/** * 懶漢式: * 全局變數初始化放到了實例化方法中,延遲產生對象。 * 但是當多個線程統一訪問時,有可能出現線程不安全的情況。需要優化。 * @author 碼歌老薛 * @date 創建時間 猴年馬月 * @version 1.0 */ public class SingleLazy4 { //提供靜態的全局變數 作為訪問該類實例的入口 但是這裡不立即載入 private volatile static SingleLazy4 sh = null; /** * 構造器私有 無法創建對象 */ private SingleLazy4(){ System.out.println("被調用了"); } /** * 雙重校驗鎖式(也有人把雙重校驗鎖式和懶漢式歸為一類)分別在代碼鎖前後進行判空校驗 * ,雙重校驗鎖式是線程安全的。然而,在JDK1.5以前,DCL是不穩定的,有時也可能創建多個實例, * 在1.5以後開始提供volatile關鍵字修飾變數來達到穩定效果。 * 雙重校驗鎖DCL(double checked locking) * @return * @throws InterruptedException */ public static SingleLazy4 getInstance() { if(sh == null){ synchronized(SingleLazy4.class){ if(sh == null){ sh = new SingleLazy4(); //return singleton; //有人提議在此處進行一次返回 } //return singleton; //也有人提議在此處進行一次返回 } } return sh; } } 上海尚學堂Java培訓 shsxt.com 獲取更多java學習資料
靜態內部類
/** *靜態內部類 * * @author 碼歌老薛 * @date 創建時間 猴年馬月 * @version 1.0 */ public class SingleInner { /** *靜態內部類式和餓漢式一樣,同樣利用了ClassLoader的機制保證了線程安全; *不同的是,餓漢式在Singleton類被載入時(從代碼段3-2的Class.forName可見) *就創建了一個實例對象,而靜態內部類即使Singleton類被載入也不會創建單例對象, *除非調用裡面的getInstance()方法。因為當Singleton類被載入時 *,其靜態內部類SingletonHolder沒有被主動使用。只有當調用getInstance方法時, *才會裝載SingletonHolder類,從而實例化單例對象。 這樣,通過靜態內部類的方法就實現了lazy loading,很好地將懶漢式和餓漢式結合起來, 既實現延遲載入,保證系統性能,也能保證線程安全 */ private static class SingleInnerHolder{ private static SingleInner instance = new SingleInner(); } private SingleInner(){ System.out.println("我被調用了"); } public static SingleInner getInstance(){ return SingleInnerHolder.instance; } }
枚舉單例
/** * jvm提供底層保證 * 不可能出現序列化、反射產生對象的漏洞 但是不能做到延遲載入 在外部,可以通過EnumSingleton.INSTANCE.work()來調用work方法。預設的枚舉實例的創建是線程安全的 、,但是實例內的各種方法則需要程式員來保證線程安全。 總的來說,使用枚舉單例模式,有三個好處: 1.實例的創建線程安全,確保單例。2.防止被反射創建多個實例。3.沒有序列化的問題。 * @author 碼歌老薛 * @date 創建時間 猴年馬月 * @version 1.0 */ public enum SingleEnum { //實例化對象 INSTANCE; /** * 對象需要執行的功能 */ void getInstance(){ } }
上海尚學堂java培訓 shsxt.com
反射/序列化 獲取對象 以及防止方式
import java.io.ObjectStreamException; import java.io.Serializable; /** * 懶漢式: * 全局變數初始化放到了實例化方法中,延遲產生對象。 * 但是當多個線程統一訪問時,有可能出現線程不安全的情況。需要優化。 * @author 碼歌老薛 * @date 創建時間 猴年馬月 * @version 1.0 */ public class SingleLazy implements Serializable{ //提供靜態的全局變數 作為訪問該類實例的入口 但是這裡不立即載入 private static SingleLazy sh = null; /** * 構造器私有 無法創建對象 */ private SingleLazy(){ if(sh!=null){ throw new RuntimeException(); } System.out.println("構造函數被調用了"); } /** * 對外提供get方法獲取 該類的實例 * @return * @throws InterruptedException */ public static synchronized SingleLazy getInstance() { if(sh==null){ sh = new SingleLazy(); } return sh; } private Object readResolve()throws ObjectStreamException{ return sh; } }
上海尚學堂java培訓 shsxt.com
用法總結:
1、懶漢式效率是最低的。
2、占用資源少 不需要延時載入 枚舉優於 餓漢式
3、占用資源比較多 需要延時載入 靜態內部類 優於 懶漢式
更多Java技術文章歡迎閱讀上海尚學堂Java培訓,免費試學和線上公開課培訓課程等你學習。