首頁技術(shù)文章正文

線程安全單例有哪些?

更新時(shí)間:2021-09-30 來源:黑馬程序員 瀏覽量:

單例模式有很多實(shí)現(xiàn)方法,餓漢、懶漢、靜態(tài)內(nèi)部類、枚舉類,試分析每種實(shí)現(xiàn)下獲取單例對(duì)象(即調(diào)用getInstance)時(shí)的線程安全,并思考注釋中的問題。

餓漢式:類加載就會(huì)導(dǎo)致該單實(shí)例對(duì)象被創(chuàng)建

懶漢式:類加載不會(huì)導(dǎo)致該單實(shí)例對(duì)象被創(chuàng)建,而是首次使用該對(duì)象時(shí)才會(huì)創(chuàng)建

1632986290784_安全單利.png

1. 餓漢單例

// 問題1:為什么加 final
// 問題2:如果實(shí)現(xiàn)了序列化接口, 還要做什么來防止反序列化破壞單例
public final class Singleton implements Serializable {
    // 問題3:為什么設(shè)置為私有? 是否能防止反射創(chuàng)建新的實(shí)例?
    private Singleton() {}
    // 問題4:這樣初始化是否能保證單例對(duì)象創(chuàng)建時(shí)的線程安全?
    private static final Singleton INSTANCE = new Singleton();
    // 問題5:為什么提供靜態(tài)方法而不是直接將 INSTANCE 設(shè)置為 public, 說出你知道的理由
    public static Singleton getInstance() {
        return INSTANCE;
    }
    public Object readResolve() {
        return INSTANCE;
    }
}


2.枚舉單例

// 問題1:枚舉單例是如何限制實(shí)例個(gè)數(shù)的
// 問題2:枚舉單例在創(chuàng)建時(shí)是否有并發(fā)問題
// 問題3:枚舉單例能否被反射破壞單例
// 問題4:枚舉單例能否被反序列化破壞單例
// 問題5:枚舉單例屬于懶漢式還是餓漢式
// 問題6:枚舉單例如果希望加入一些單例創(chuàng)建時(shí)的初始化邏輯該如何做
enum Singleton {
    INSTANCE;
}


3. 懶漢單例

public final class Singleton {
    private Singleton() { }
    private static Singleton INSTANCE = null;
    // 分析這里的線程安全, 并說明有什么缺點(diǎn)
    public static synchronized Singleton getInstance() {
        if( INSTANCE != null ){
            return INSTANCE;
        }
    INSTANCE = new Singleton();
    return INSTANCE;
    }
}


4. DCL 懶漢單例

public final class Singleton {
    private Singleton() { }
    // 問題1:解釋為什么要加 volatile ?
    private static volatile Singleton INSTANCE = null;
    // 問題2:對(duì)比實(shí)現(xiàn)3, 說出這樣做的意義
    public static Singleton getInstance() {
        if (INSTANCE != null) {
            return INSTANCE;
        }
        synchronized (Singleton.class) {
        // 問題3:為什么還要在這里加為空判斷, 之前不是判斷過了嗎
            if (INSTANCE != null) { // t2
                return INSTANCE;
            }
            INSTANCE = new Singleton();
            return INSTANCE;
        }
    }
}


5. 靜態(tài)內(nèi)部類懶漢單例

public final class Singleton {
    private Singleton() { }
    // 問題1:屬于懶漢式還是餓漢式
    private static class LazyHolder {
        static final Singleton INSTANCE = new Singleton();
    }
    // 問題2:在創(chuàng)建時(shí)是否有并發(fā)問題
    public static Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}

IT培訓(xùn)班


猜你喜歡:

Java如何處理高并發(fā)?Java高并發(fā)處理

如何解決秒殺的高并發(fā)?

Java并發(fā)編程:Callable、Future和FutureTask

黑馬程序員JavaEE高手班

分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!