三、[推]列舉模式
四、[推]holder模式
五、總結
不想看過程的可以直接看結果
執行緒安全
懶載入反射破壞
餓漢模式
類載入就建立物件確保執行緒安全
立即載入
能避免懶漢模式
synchronized
synchronized對方法加鎖
懶載入不能避免
雙重檢測鎖
volatile(jdk>1.5)+判定+對類加鎖
懶載入不能避免
列舉模式
靜態**塊建立物件確保執行緒安全
立即載入
能避免holder模式(作者最愛)
載入內部類就建立物件確保執行緒安全
懶載入能避免
單例模式相信大家都很熟悉了,是一種很常用的設計模式,單例模式確保乙個類只有乙個例項,並提供乙個訪問它的全域性訪問點。作者曾經在一次面試中要求寫出單例模式,想了想單例模式還是簡單的,隨手就寫了如下**。
/**
* @author meng
* @date 2020/8/8
*/public
class
singleton
public
static singleton getinstance()
return instance;
}}
最後,不出意外的沒有通過面試。原因如下
這段**並沒***執行緒是安全的,是有可能導致獲取的物件不唯一。
這段**是可以通過反射破壞單例模式,拿到多個相同的物件。
在多執行緒的情況下,乙個執行緒已經進入到if裡面的**塊但是還沒有建立物件,突然切換到另外乙個執行緒,就有可能匯出建立的物件不一致。
執行緒a執行緒b
判斷物件不為空
判斷物件不為空
建立物件
返回物件
建立物件
返回物件
至於通過反射破壞單例模式,我們則是通過setaccessible(true)來強行訪問私有構造器,**如下
public
static
void
main
(string[
] args)
throws nosuchmethodexception, illegalacces***ception, invocationtargetexception, instantiationexception
經過總結,乙個單例模式的寫法,我們需要關注以下幾點。
/**
- @author meng
- @date 2020/8/10
*/public
class
singleton
}public
static
synchronized singleton getinstance()
}
餓漢模式的特點很明顯,它在類初始化的時候會建立物件,而該過程執行在類初始化()
,而()
是執行緒安全的,因此不擔心執行緒安全問題,但是缺點也容易明顯,就算沒有使用也會建立物件,容易浪費記憶體。同時構造器進行了判斷,如果想通過反射也會丟擲異常。
懶漢模式,顧名思義,就是很懶,用到才建立物件,屬於懶載入。作者一開始的例子就屬於懶漢模式,因此我們需要為其確保執行緒安全。但是懶漢模式難以防止反射破壞,詳情下面會分析
/**
- @author meng
- @date 2020/8/10
*/public
class
singleton
}public
static
synchronized singleton getinstance()
return instance;
}}
簡單粗暴,直接通過synchronized加鎖達到了執行緒安全,也像餓漢模式一樣在建構函式進行了判斷防止反射破壞。但是真的能防止反射嗎?它防止的只是先正常獲取物件,再反射,但是其實可以通過先反射,再正常的獲取物件,拿到兩個物件。**如下
public
static
void
main
(string[
] args)
throws nosuchmethodexception, illegalacces***ception, invocationtargetexception, instantiationexception
/**
- @author meng
- @date 2020/8/11
*/public
class
singleton
}public singleton getinstance()
}}return instance;
}}
該方法不是對整個方法加鎖,而是先進行判斷,再對類進行加鎖,同時使用volatile避免指令的重排序(需要jdk1.5以後),volatile關鍵字的作用這裡就不細談了。至於防止反射破壞,與上面的一樣,是不能避免的。
/**
3. @author meng
4. @create 2020/8/112
*/public
enum singleton
}
我們先看看列舉的本質
列舉只能擁有私有的構造器
列舉類實際上是乙個繼承enum的乙個final類
列舉類不允許被反序列化,enum重寫了方法
靜態**塊中對final變數的值進行初始化
enum類最終是乙個final class
列舉是執行緒安全的,所以列舉類裡的列舉會在靜態**塊建立物件,而該過程執行在類初始化()
,而()
是執行緒安全的
接下來就是作者最喜歡的holder模式,雖然列舉模式已經十分的完美,但是物件導向還是更多人喜歡class而不是enum.holder模式說白了就是通過靜態內部類來實現,先看**
/**
* @author meng
* @date 2020/8/11
*/public
class
singleton
}private
static
class
holder
public
static singleton getinstance()
}
在呼叫getinstance方法的時候,holder類才會被載入(這裡可以去看下類載入的時機),到了初始化階段會對靜態變數instance賦值,屬於()
過程,而該過程是保證執行緒安全的,靜態內部類在用到時候才會載入,因此該模式屬於延遲載入,與餓漢模式類似,私有構造方法進行判定避免了反射破壞。
執行緒安全
懶載入反射破壞
餓漢模式
類載入就建立物件確保執行緒安全
立即載入
能避免懶漢模式
synchronized
synchronized對方法加鎖
懶載入不能避免
雙重檢測鎖
volatile(jdk>1.5)+判定+對類加鎖
懶載入不能避免
列舉模式
靜態**塊建立物件確保執行緒安全
立即載入
能避免holder模式(作者最愛)
載入內部類就建立物件確保執行緒安全
懶載入能避免
看完這篇TCP,和面試官扯皮就沒問題了
無論什麼技術崗位,計算機網路幾乎是每場面試的必問內容,在面試 現的次數非常非常多,所以我面試之前也有所準備。看到csdn上介紹http的部落格比較多,tcp的比較少,於是今天結合面試問題先詳細講一講tcp。這部分之所以放在最前面,因為太重要!太重要!太重要了!源埠 目標埠 計算機上的程序要和其他程序...
面試官系統之設計模式(單例模式)
單例模式 顧名思義就是只能有乙個,不能在出現第二個。就如同地球上沒有兩片完全一模一樣的樹葉一樣。程式猿的角度理解 乙個類有且只能有乙個例項,不能出現第二個,並且整個專案系統中都能訪問該例項。面試官 為啥不能出現第二個?程式猿 這個面試官是笨蛋,出現第二個那就不叫單例模式了,那至少得叫雙例模式,是吧?...
吊錘面試官的單例模式大全
餓漢一 餓漢式優點 寫法簡單 執行緒安全的 缺點 還沒被呼叫就物件就被載入了,不夠節約 public class singleton public static singleton getinstance 測試方法用於證明餓漢單例模式下fianl修飾單例物件的作用 注意必須是餓漢式,懶漢式不考慮使用...