曾經到一家公司面試,面試中問了java設計模式中的單例模式,讓我用筆寫出來,當時可能自己的技術還沒有形成體系,思路也不是很清晰,結果在一張紙上面寫的亂七八糟的,塗抹的不成樣子,不堪入目。時常想起當時的情境,真的很難讓自己忘掉,但是這種經曆對我來說也是有好處的,讓我對單例模式有了更多的認識。
首先想一下如何能保證一個Java類在整個應用上下文多線程環境當中只有一個:
第一點:不能寫public的構造器,避免對該類進行new對象操作;
第二點:保證單例對象屬性和方法是屬於類層級的,符合java bean的規範,屬性不對外暴露,只對外提供公有存取方法;
第三點:保證建立單例對象是安全執行緒的;
接下來從代碼看看:
1、懶漢式:用到的時候再去建立,並不能保證安全執行緒,需要添加鎖機制
public class Singleton {// 私人類變數private static Singleton singleton;// 私人構造器private Singleton() {}// 公有類方法public static /*synchronized*/ Singleton getInstance() {//synchronized (Singleton.class) {// 用到的時候再建立if (singleton == null) {singleton = new Singleton();}return singleton;//}}}
2、餓漢式:先建立,想用的時候直接用,這種方式應該就是安全執行緒的了,類載入(classLoader)階段就執行個體化了Singleton
public class Singleton {// 私人類變數private static final Singleton singleton = new Singleton();// 私人構造器private Singleton() {}// 公有類方法public static Singleton getInstance() {// 想用就直接用return singleton;}}
3、雙重檢查機制:如果單例對象為空白,先擷取類鎖,然後再次判斷單例對象是否為空白,為空白就建立對象
public class Singleton {// 私人類變數,volatile變數禁止指令重排序private static volatile Singleton singleton;// 私人構造器private Singleton() {}// 公有類方法public static Singleton getInstance() {if(singleton == null){synchronized (Singleton.class) {if (singleton == null) {singleton = new Singleton();}}}return singleton;}}
4、靜態內部類:在類的內部定義一個靜態內部類,在調用內部類時才初始化,只執行一次,保證安全執行緒
public class Singleton {// 私人構造器private Singleton() {}// 公有類方法public static Singleton getInstance() {return InnerSingleton.instance;}// 靜態內部類static final class InnerSingleton {private static final Singleton instance = new Singleton();}}
5、靜態代碼塊:在類載入階段就被執行個體化,靜態代碼塊只執行一次。
public class Singleton {private static Singleton singleton;static{singleton = new Singleton();}// 私人構造器private Singleton() {}// 公有類方法public static Singleton getInstance() {return singleton;}}