详解单例模式线程安全
生活随笔
收集整理的這篇文章主要介紹了
详解单例模式线程安全
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
詳解單例模式線程安全
單例模式有很多實現方法,餓漢、懶漢、靜態內部類、枚舉類,每種實現下獲取單例對象(即調用 getInstance)時的保證線程安全
- 餓漢式:類加載就會導致該單實例對象被創建
- 懶漢式:類加載不會導致該單實例對象被創建,而是首次使用該對象時才會創建
實現1: 餓漢式
// 問題1:為什么加 final,防止子類繼承后更改 // 問題2:如果實現了序列化接口, 還要做什么來防止反序列化破壞單例,如果進行反序列化的時候會生成新的對象,這樣跟單例模式生成的對象是不同的。要解決直接加上readResolve()方法就行了,如下所示 public final class Singleton implements Serializable {// 問題3:為什么設置為私有? 放棄其它類中使用new生成新的實例,是否能防止反射創建新的實例?不能。private Singleton() {}// 問題4:這樣初始化是否能保證單例對象創建時的線程安全?沒有,這是類變量,是jvm在類加載階段就進行了初始化,jvm保證了此操作的線程安全性private static final Singleton INSTANCE = new Singleton();// 問題5:為什么提供靜態方法而不是直接將 INSTANCE 設置為 public, 說出你知道的理由。//1.提供更好的封裝性;2.提供范型的支持public static Singleton getInstance() {return INSTANCE;}public Object readResolve() {return INSTANCE;} }實現2: 餓漢式
// 問題1:枚舉單例是如何限制實例個數的:創建枚舉類的時候就已經定義好了,每個枚舉常量其實就是枚舉類的一個靜態成員變量 // 問題2:枚舉單例在創建時是否有并發問題:沒有,這是靜態成員變量 // 問題3:枚舉單例能否被反射破壞單例:不能 // 問題4:枚舉單例能否被反序列化破壞單例:枚舉類默認實現了序列化接口,枚舉類已經考慮到此問題,無需擔心破壞單例 // 問題5:枚舉單例屬于懶漢式還是餓漢式:餓漢式 // 問題6:枚舉單例如果希望加入一些單例創建時的初始化邏輯該如何做:加構造方法就行了 enum Singleton {INSTANCE; }實現3:懶漢式
public final class Singleton {private Singleton() { }private static Singleton INSTANCE = null;// 分析這里的線程安全, 并說明有什么缺點:synchronized加載靜態方法上,可以保證線程安全。缺點就是鎖的范圍過大,每次訪問都會加鎖,性能比較低。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:對比實現3, 說出這樣做的意義:提高了效率public static Singleton getInstance() {if (INSTANCE != null) {return INSTANCE;}synchronized (Singleton.class) {// 問題3:為什么還要在這里加為空判斷, 之前不是判斷過了嗎?這是為了第一次判斷時的并發問題。if (INSTANCE != null) { // t2return INSTANCE;}INSTANCE = new Singleton();return INSTANCE;}} }實現5:靜態內部類懶漢式
public final class Singleton {private Singleton() { }// 問題1:屬于懶漢式還是餓漢式:懶漢式,這是一個靜態內部類。類加載本身就是懶惰的,在沒有調用getInstance方法時是沒有執行LazyHolder內部類的類加載操作的。private static class LazyHolder {static final Singleton INSTANCE = new Singleton();}// 問題2:在創建時是否有并發問題,這是線程安全的,類加載時,jvm保證類加載操作的線程安全public static Singleton getInstance() {return LazyHolder.INSTANCE;} }總結
以上是生活随笔為你收集整理的详解单例模式线程安全的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: charset参数 sqluldr2_s
- 下一篇: 逻辑综合——概述与基本概念