public class Singleton { private static Singleton instance; //私有靜態自身類屬性,因爲靜態方法只能訪問靜態成員,所以是靜態的 private Singleton (){} //私有構造器 public static Singleton getInstance() { //給外界提供單例類對象的靜態函數函數:因爲使用第一次從單例類中獲取單例對象的時候,沒有初始化當前類對象,所以只能經過類調用靜態方法的形式 if (instance == null) { instance = new Singleton(); } return instance; } }
public class Singleton { private static Singleton instance; //私有靜態自身類屬性,因爲靜態方法只能訪問靜態成員,所以是靜態的 private Singleton (){} //私有構造器 public static synchronized Singleton getInstance() { //給外界提供單例類對象的靜態函數函數:因爲使用第一次從單例類中獲取單例對象的時候,沒有初始化當前類對象,所以只能經過類調用靜態方法的形式 if (instance == null) { instance = new Singleton(); } return instance; } }
public class Singleton { private static Singleton instance; //私有靜態自身類屬性,因爲靜態方法只能訪問靜態成員,所以是靜態的 private Singleton (){} //私有構造器 public static synchronized Singleton getInstance() { //給外界提供單例類對象的靜態函數函數:因爲使用第一次從單例類中獲取單例對象的時候,沒有初始化當前類對象,所以只能經過類調用靜態方法的形式 if (instance == null) { //Single Checked synchronized (Singleton.class) { if (instance == null) { //Double Checked 第二次檢查的緣由:有可能多個線程同時經過了第一個檢查,可是遇到了同步操做,其中一個線程獲取了操做權,所以必須再一次判斷,不然後面的線程會再次建立一個對象 instance = new Singleton(); } } } return instance ; } }
這段代碼看起來很完美,很惋惜,它是有問題。主要在於instance = new Singleton()這句,這並不是是一個原子操做,事實上在 JVM 中這句話大概作了下面 3 件事情。spring
可是在 JVM 的即時編譯器中存在指令重排序的優化。也就是說上面的第二步和第三步的順序是不能保證的,最終的執行順序多是 1-2-3 也多是 1-3-2。若是是後者,則在 3 執行完畢、2 未執行以前,被線程二搶佔了,這時 instance 已是非 null 了(但卻沒有初始化),因此線程二會直接返回 instance,而後使用,而後瓜熟蒂落地報錯。安全
public class Singleton { private volatile static Singleton instance; //聲明成 volatile private Singleton (){} public static Singleton getSingleton() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
public class Singleton{ //類加載時就初始化 private static final Singleton instance = new Singleton(); //使用final關鍵字保證instance對象只能初始化一次,其後不變 private Singleton(){} public static Singleton getInstance(){ return instance; } }
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
public enum EasySingleton{ INSTANCE; //默認是使用public static final修飾 }
class Season{ //1.提供類的屬性,聲明爲private final private final String seasonName; private final String seasonDesc; //2.聲明爲final的屬性,在構造器中初始化。 private Season(String seasonName,String seasonDesc){ this.seasonName = seasonName; this.seasonDesc = seasonDesc; } //3.經過公共的方法來調用屬性 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } //4.建立枚舉類的對象:將類的對象聲明public static final public static final Season SPRING = new Season("spring", "春暖花開"); //若是隻有一個對象,那麼這個類就是一種單例模式的實現,和相似餓漢式,使用靜態本類屬性,一加載當前類就初始化,不一樣的是經過類名獲取單一實例 public static final Season SUMMER = new Season("summer", "夏日炎炎"); public static final Season AUTUMN = new Season("autumn", "秋高氣爽"); public static final Season WINTER = new Season("winter", "白雪皚皚"); @Override public String toString() { return "Season [seasonName=" + seasonName + ", seasonDesc=" + seasonDesc + "]"; } public void show(){ System.out.println("這是一個季節"); } }