更新時(shí)間:2021-09-30 來(lái)源:黑馬程序員 瀏覽量:
單例模式有很多實(shí)現(xiàn)方法,餓漢、懶漢、靜態(tài)內(nèi)部類、枚舉類,試分析每種實(shí)現(xiàn)下獲取單例對(duì)象(即調(diào)用getInstance)時(shí)的線程安全,并思考注釋中的問(wèn)題。
餓漢式:類加載就會(huì)導(dǎo)致該單實(shí)例對(duì)象被創(chuàng)建
懶漢式:類加載不會(huì)導(dǎo)致該單實(shí)例對(duì)象被創(chuàng)建,而是首次使用該對(duì)象時(shí)才會(huì)創(chuàng)建
1. 餓漢單例
// 問(wèn)題1:為什么加 final // 問(wèn)題2:如果實(shí)現(xiàn)了序列化接口, 還要做什么來(lái)防止反序列化破壞單例 public final class Singleton implements Serializable { // 問(wèn)題3:為什么設(shè)置為私有? 是否能防止反射創(chuàng)建新的實(shí)例? private Singleton() {} // 問(wèn)題4:這樣初始化是否能保證單例對(duì)象創(chuàng)建時(shí)的線程安全? private static final Singleton INSTANCE = new Singleton(); // 問(wèn)題5:為什么提供靜態(tài)方法而不是直接將 INSTANCE 設(shè)置為 public, 說(shuō)出你知道的理由 public static Singleton getInstance() { return INSTANCE; } public Object readResolve() { return INSTANCE; } }
2.枚舉單例
// 問(wèn)題1:枚舉單例是如何限制實(shí)例個(gè)數(shù)的 // 問(wèn)題2:枚舉單例在創(chuàng)建時(shí)是否有并發(fā)問(wèn)題 // 問(wèn)題3:枚舉單例能否被反射破壞單例 // 問(wèn)題4:枚舉單例能否被反序列化破壞單例 // 問(wèn)題5:枚舉單例屬于懶漢式還是餓漢式 // 問(wèn)題6:枚舉單例如果希望加入一些單例創(chuàng)建時(shí)的初始化邏輯該如何做 enum Singleton { INSTANCE; }
3. 懶漢單例
public final class Singleton { private Singleton() { } private static Singleton INSTANCE = null; // 分析這里的線程安全, 并說(shuō)明有什么缺點(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() { } // 問(wèn)題1:解釋為什么要加 volatile ? private static volatile Singleton INSTANCE = null; // 問(wèn)題2:對(duì)比實(shí)現(xiàn)3, 說(shuō)出這樣做的意義 public static Singleton getInstance() { if (INSTANCE != null) { return INSTANCE; } synchronized (Singleton.class) { // 問(wèn)題3:為什么還要在這里加為空判斷, 之前不是判斷過(guò)了嗎 if (INSTANCE != null) { // t2 return INSTANCE; } INSTANCE = new Singleton(); return INSTANCE; } } }
5. 靜態(tài)內(nèi)部類懶漢單例
public final class Singleton { private Singleton() { } // 問(wèn)題1:屬于懶漢式還是餓漢式 private static class LazyHolder { static final Singleton INSTANCE = new Singleton(); } // 問(wèn)題2:在創(chuàng)建時(shí)是否有并發(fā)問(wèn)題 public static Singleton getInstance() { return LazyHolder.INSTANCE; } }
猜你喜歡: