設(shè)計模式學(xué)習(xí)05----之單例模式

單例模式,是我們最常用也最熟悉的一種設(shè)計模式,其使用要注意線程安全。
定義

單例模式:顧名思義,就是在應(yīng)用中有且只有一個實例。一般類似于計數(shù)器類的都必須是單例,多例會導(dǎo)致計數(shù)結(jié)果不準(zhǔn)。
一般而言,其分為餓漢式和懶漢式。
懶漢式

懶漢式:顧名思義,就是不在系統(tǒng)加載時創(chuàng)建類的實例。而是在調(diào)用時才去一次性創(chuàng)建。
demo如下:

package com.singleton;

/**
 * 懶漢式
 * @author xiang.wei
 */
public class LazySingleton {
    /**
     * 定義一個私有變量,目的是外部不能直接訪問該變量,必須通過公共的訪問方法來訪問
     */
    private static LazySingleton instance=null;

    /**
     * 私有化構(gòu)造器,使之不能直接構(gòu)造對象
     */
    private LazySingleton(){
       
    }

    /**
     * 公共的提取對象的方法
     * @return
     */
    public synchronized static LazySingleton getInstance() {
        if (instance==null) {
             instance=new LazySingleton();
        }
        return instance;
    }
}



餓漢式

餓漢式:與懶漢式相反,餓漢式就是在系統(tǒng)加載時就去創(chuàng)建類的實例。
demo如下:

package com.singleton;

/**
 * 餓漢式
 * @author xiang.wei
 * @create 2018/4/10 10:34
 */
public class HungrySingleton {
    private static final HungrySingleton SINGLETON = new HungrySingleton();

    private HungrySingleton() {
    }

    public static HungrySingleton getInstance() {
        return SINGLETON;
    }
}



總結(jié):餓漢式與懶漢式相比要占用更多的內(nèi)存,因為系統(tǒng)加載之后就會創(chuàng)建實例。但是效率要比懶漢式要高。
雙重加鎖

雙重加鎖是懶漢式的一種擴(kuò)展。因為直接在getInstance()上加上synchronized會導(dǎo)致每次調(diào)用方法時都需要加鎖。執(zhí)行效率不高。所以,我們采用了雙重加鎖的方式。

package com.singleton;

/**
 * 懶漢式
 * 雙重加鎖
 * @author xiang.wei
 */
public class LazySingleton_two {
    /**
     * 定義一個私有變量,目的是外部不能直接訪問該變量,必須通過公共的訪問方法來訪問
     */
    private static  volatile LazySingleton_two instance = null;

    /**
     * 私有化構(gòu)造器,使之不能直接構(gòu)造對象
     */
    private LazySingleton_two() {

    }

    /**
     * 公共的提取對象的方法
     *
     * @return
     */
    public static LazySingleton_two getInstance() {
        //如果單例存在則直接返回
        if (instance == null) {
            //單例不存在,則進(jìn)入同步代碼塊
            synchronized (LazySingleton_two.class) {
                if (instance == null) {
                    System.out.println("實例化的次數(shù)");
                    instance = new LazySingleton_two();
                }
            }
        }
        return instance;
    }
}

 

雙重加鎖并不是加兩個synchronized關(guān)鍵字。
第一個判斷是當(dāng)對象存在時則直接返回實例,當(dāng)對象不存在時則進(jìn)入同步代碼塊中,同步代碼塊的作用跟之前是相同的,就是防止兩個線程同時訪問同步代碼塊的內(nèi)容,造成生成多個實例的情況。同步代碼塊每次只允許一個線程進(jìn)入,創(chuàng)建完實例后返回。第二個判斷是當(dāng)多個線程排隊進(jìn)入代碼塊時,第一個線程創(chuàng)建完實例返回后,第二個線程再進(jìn)入時,不需要在創(chuàng)建實例。
采用雙重加鎖后,代碼的執(zhí)行效率有了較大的提升。
靜態(tài)內(nèi)部類的方式

public class MySingleton {

    private static class MySingletonHandle {
        private static final MySingleton instance = new MySingleton();
    }

    private MySingleton() {

    }

    public MySingleton getSingleton() {
        return MySingletonHandle.instance;
    }
}





作者:碼農(nóng)飛哥
微信公眾號:碼農(nóng)飛哥