1. 程式人生 > >Java設計模式-單例模式(二)單例模式類

Java設計模式-單例模式(二)單例模式類

餓漢式單例類

餓漢式單例類在載入時單例物件已經被建立。程式碼如下:

/**
 * 懶漢式單例
 * @Author: Rick
 * @Date: 2018/10/31 17:44
 */
public class EagerSingleton {
    private static EagerSingleton eagerSingleton = new EagerSingleton();

    private EagerSingleton(){};

    public static EagerSingleton getEagerSingleton(){
        return eagerSingleton;
    }
}

懶漢式單例類

與餓漢式單例不一樣的是,懶漢式單例在第一次建立時被例項化。

使用關鍵字synchronized,使用執行緒鎖,實現單例模式,程式碼如下:

**
 * 懶漢式單例
 * @Author: Rick
 * @Date: 2018/10/31 17:51
 */
public class LazySingleton {
    private static LazySingleton lazySingleton = null;

    private LazySingleton(){

    }
    //增加了執行緒鎖,執行緒安全,但是增加了系統壓力,使效能降低
   synchronized public static LazySingleton getLazySingleton() {
        if (lazySingleton == null) {
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
    
}

在類上新增關鍵字synchronized,進行單例實現,得到了執行緒安全,但每次都要進行執行緒鎖的判斷,在多執行緒高併發的訪問環境中,導致系統的效能大大降低。getLazySingleton()方法修改為:

public static LazySingleton getLazySingleton(){
        if(lazySingleton == null){
            synchronized (LazySingleton.class){
                lazySingleton = new LazySingleton();
            }
        }
        return lazySingleton;
    }

問題:這種方式不能實現單例,在第一個請求到達時,會建立物件,如果此時有第二個呼叫該方法,就會線上程鎖外等待,當第一個請求建立物件完成後,第二個請求處於等待的狀態,會再建立一個物件,所以這種寫法無法實現單例。 使用雙重檢查鎖定實現懶漢式的單例類的完整程式碼如下:

public static LazySingleton getLazySingleton(){
        if(lazySingleton == null){
            synchronized (LazySingleton.class){
                if(lazySingleton == null) {
                    lazySingleton = new LazySingleton();
                }
            }
        }
        return lazySingleton;
    }

靜態內部類單例

餓漢式單例不能實現延遲載入,不論將來使用與否都會佔用記憶體;懶漢式單例類執行緒安全控制繁瑣,影響系統性能。可見無論是哪個都存在一些問題。使用靜態內部類來實現單例,可以解決以上問題,程式碼如下:

/**
 * 內部類實現單例
 * @Author: Rick
 * @Date: 2018/10/31 18:25
 */
public class InternalSingleton {
    private InternalSingleton(){
    }

    private static class HolderClass{
        /**內部類中進行例項化*/
        private final static  InternalSingleton INTERNALSINGLETON = new InternalSingleton();
    }

    public static InternalSingleton getHolderClass() {
        return HolderClass.INTERNALSINGLETON;
    }

    public static void main(String[] args) {
        InternalSingleton internalSingleton1,internalSingleton2;
        internalSingleton1 = InternalSingleton.getHolderClass();
        internalSingleton2 = InternalSingleton.getHolderClass();

        System.out.println(internalSingleton1 == internalSingleton2);

    }
}