Java編寫單例類的幾種方式

1.餓漢式

public class HungerySingleton {
 
    //ClassLoader 類加載時立即實例化對象,僅實例化一次,線程安全的
    private static HungerySingleton hungerySingleton = new HungerySingleton();
 
 
    public static HungerySingleton getInstance(){
        return hungerySingleton;
    }
 
}

優點:僅實例化一次,線程是安全的。獲取實例的速度快

缺點:類加載時立即實例化對象,可能實例化的對象不被使用,造成內存的浪費。

2.懶漢式

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,造成對象重複實例化。

3.雙重檢查鎖 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 HoonSingleton();
                }
            }
        }
        return hoonSingleton;
    }

優點:1、線程安全。注意加粗標記,進行雙重檢查,保證只在實例未初始化前進行同步,效率高。

            2、對hoonSingleton使用volatile修飾符,避免實例化過程中產生的重排序。避免NPE拋出。

缺點:實例非空判斷,耗費一定資源

4.Holder方式 廣泛使用的一種單例模式

//聲明類的時候、成員變量中不聲明實例變量,而是放到內部靜態類中
public class HolderDemo {
 
    private static class Holder{
        private static HolderDemo instance = new HolderDemo();
    }
 
    public static HolderDemo getInstance(){
        return Holder.instance;
    }
}

優點:1、內部類只有在外部類被調用才加載,從而實現了延遲加載

            2、線程安全。且不用加鎖。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章