一、餓漢式
public class HungerySingleton { //ClassLoader 類加載時立即實例化對象,僅實例化一次,線程安全的 private static HungerySingleton hungerySingleton = new HungerySingleton(); public static HungerySingleton getInstance(){ return hungerySingleton; } //利用線程輸出(后面就不寫了哈) public static void main(String[]args){ for(int i=0;i<20;i++){ Thread thread =new Thread() { @Override public void run() { HungerySingleton hungerySingleton = HungerySingleton.getInstance(); System.out.println(hungerySingleton); } }; thread.start(); } } }
優點:僅實例化一次,線程是安全的。獲取實例的速度快
缺點:類加載時立即實例化對象,可能實例化的對象不被使用,造成內存的浪費。
二、懶漢式
public class HoonSingleton { //不能保證實例對象的唯一性 private static HoonSingleton hoonSingleton = null; public static HoonSingleton getInstance(){ if(hoonSingleton==null){ hoonSingleton = new HoonSingleton(); } return hoonSingleton; } }
優點:獲取實例時才進行實例的初始化,節省系統資源
缺點:1、如果獲取實例時,初始化的工作量較多,加載速度會變慢,影響系統系能
2、每次獲取實例都要進行非空檢查,系統開銷大
3、非線程安全。注意紅色代碼標記,當多個線程同時getInstance()時,可能hoonSingleton實例化未完成,hoonSingleton==null判斷均為true,造成對象重復實例化。
三、雙重檢查鎖 DCL(double-checked locking)+ volatile
public class HoonSingleton { private static volatile HoonSingleton hoonSingleton = null; // 使用sync同步HoonSingleton.class 兩次判斷hoonSingleton是否為null 避免並發導致hoonSingleton被重新實例化 // 並沒有對整個方法使用sync,鎖的粒度變小了,實現了實例對象的唯一性 public static HoonSingleton getInstance(){ if(hoonSingleton==null){ synchronized (HoonSingleton.class) { if(hoonSingleton==null) { hoonSingleton = new DCL(); } } } return hoonSingleton; }
優點:1、線程安全。注意加粗標記,進行雙重檢查,保證只在實例未初始化前進行同步,效率高。
2、對hoonSingleton使用volatile修飾符,避免實例化過程中產生的重排序。避免NPE拋出。
缺點:實例非空判斷,耗費一定資源
四、Holder方式 廣泛使用的一種單例模式
//聲明類的時候、成員變量中不聲明實例變量,而是放到內部靜態類中 public class HolderDemo { private static class Holder{ private static HolderDemo instance = new HolderDemo(); } public static HolderDemo getInstance(){ return Holder.instance; } }
優點:1、內部類只有在外部類被調用才加載,從而實現了延遲加載
2、線程安全。且不用加鎖。
五、使用枚舉的單例模式,本質上和餓漢模式沒有任何區別,只是采用Enum實現的更巧妙了
public enum EnumSingleton { //枚舉類型,在加載的時候實例化。 INSTANCE; public static EnumSingleton getInstance(){ return INSTANCE; } }
優點:僅實例化一次,線程是安全的。獲取實例的速度快
缺點:類加載時立即實例化對象,可能實例化的對象不被使用,造成內存的浪費。
六、枚舉和懶漢模式相結合
public class EnumSingletonDemo { private enum EnumHolder{ INSTANCE; private static EnumSingletonDemo instance=null; private EnumSingletonDemo getInstance(){ if(instance ==null) { instance = new EnumSingletonDemo(); } return instance; } } //實現懶加載 public static EnumSingletonDemo getInstance(){ return EnumHolder.INSTANCE.getInstance(); }
優點:1、線程安全。且不用加鎖。
2、實現了懶加載
缺點:仍然需要實例非空判斷,耗費一定資源