java中五種單例模式

堅持每天寫博文,記錄開發中的點點滴滴

  • 餓漢式
    餓漢式
    餓漢式可以說是我們最先接觸單例模式的例子了,是最基本的單例寫法,也是最快最懶的方式。
    優點:簡單好寫;缺點:類加載就初始化了對象,影響應用啓動速度
package singleton;
/**
 * 
* @ClassName: BaseSingleton 
* @Description: TODO(餓漢式單例模式) 
* @author Allen 
* @date 2018年1月11日 上午10:08:13 
*
 */
public class BaseSingleton {

    //第一步:私有構造
    private BaseSingleton() {

    }
    //第二步,私有靜態對象
    private static BaseSingleton INSTANCE = new BaseSingleton();
    //第三步:提供對外獲取方法
    public static BaseSingleton getBaseSingleton() {
        return INSTANCE;
    }
}
  • 懶漢式 主要是針對於餓漢式的缺點
    優點:只有第一次使用時纔會初始化對象;缺點:多線程中可能出現創建多個對象
    其實就是加了個空判斷
package singleton;
/**
 * 
* @ClassName: LazyLoadSingleton 
* @Description: TODO(懶漢式單例) 
* @author Allen 
* @date 2018年1月11日 上午10:17:27 
*
 */
public class LazyLoadSingleton {

    //第一步:私有構造
    private LazyLoadSingleton() {

    }
    //第二步:私有靜態對象
    private static LazyLoadSingleton INSTANCE;
    //第三步:如果存在實例給出獲取方法,不存在創建
    public LazyLoadSingleton getLazyLoadSingleton() {
        if(INSTANCE == null) {
            INSTANCE = new LazyLoadSingleton();
        }
            return INSTANCE;
    }
}
  • 同步鎖式
    因爲懶漢式的出現,雖然解決了餓漢式的不足,但也出現了多線程的問題。於是解決懶漢式的方式就出現了,那就是我們熟知的加鎖Synchronized。
    優點:保證線程安全;缺點:每次都要加鎖,但是獲取不經濟。
package singleton;
/**
 * 
* @ClassName: LazySynchronizedSingleton 
* @Description: TODO(同步鎖式單例) 
* @author Allen 
* @date 2018年1月11日 上午10:24:02 
*
 */
public class LazySynchronizedSingleton {

    //第一步:私有構造
    private LazySynchronizedSingleton() {

    }
    //第二步:創建私有對象
    private static LazySynchronizedSingleton INSTANCE;
    //第三步:提供一個同步的對外獲取方法
    public static synchronized LazySynchronizedSingleton getInstance() {
        if(INSTANCE == null) {
            INSTANCE = new LazySynchronizedSingleton();
        }
        return INSTANCE;
    }
}
  • 雙重檢測式
    第3種方式應該已經滿足日常大部分的需求,但對我們程序員來說,不斷的優化纔是學習之道。那麼針對每次獲取都會加鎖的問題,要怎麼解決呢?雙重檢測式就出現了。
    優點:第一次獲取時纔會加鎖;缺點:相比之下寫法麻煩
package singleton;
/**
 * 
* @ClassName: DoubleCheckSingleton 
* @Description: TODO(雙重檢測單例模式) 
* @author Allen 
* @date 2018年1月11日 上午10:29:39 
*
 */
public class DoubleCheckSingleton {

    //第一步:私有構造
    private DoubleCheckSingleton() {

    }
    //第二步:創建靜態對象
    private static volatile DoubleCheckSingleton INSTANCE;
    //提供對外方法
    public static DoubleCheckSingleton getInstance() {
        if(INSTANCE == null) {
            synchronized (DoubleCheckSingleton.class) {
                if(INSTANCE == null) {
                    INSTANCE = new DoubleCheckSingleton();
                }
            }
        }
        return INSTANCE;
    }
}

我們第二步用到了volatile,關於volatile不是本文的重點,所以這裏不展開說明。在第三步中,我們首先判斷一次空,如果是空,就加鎖,然後再判斷一次空,如果爲空就創建。這樣的好處就是上面優點說到的,只會鎖一次。缺點大家也發現了,不僅要必須寫volatile,方法中的步驟也不能錯。
Java中Volatile關鍵字詳解 https://www.cnblogs.com/zhengbin/p/5654805.html

  • 內部類式
    優點:懶加載、線程安全、代碼少;缺點:暫無
    內部類Holder,裏面有外部的實例。這怎麼就滿足懶漢式和線程安全呢?當我們應用初始化時,getInstance沒有被調用,就沒有實例對象,那就滿足了懶漢式。當我們調用getInstance的時候,Java虛擬機爲了保證類加載的安全性,所以這裏就保證了線程安全。

整理自:詳細的雙語言(Java與Kotlin)5種單例模式 2018-01-08 FYNN_JASON 碼個蛋

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