What
一個(gè)類只允許創(chuàng)建一個(gè)對(duì)象(或者實(shí)例),那這個(gè)類就是一個(gè)單例類撬码,這種設(shè)計(jì)模式就叫作單例設(shè)計(jì)模式,簡稱單例模式(Singleton Design Pattern)。
Why
為什么我們需要單例這種設(shè)計(jì)模式熟吏?它能解決哪些問題?
從業(yè)務(wù)概念上玄窝,有些數(shù)據(jù)在系統(tǒng)中只應(yīng)該保存一份牵寺,就比較適合設(shè)計(jì)為單例類。比如恩脂,系統(tǒng)的配置信息類帽氓。除此之外,我們還可以使用單例解決資源訪問沖突的問題俩块。
How
那么黎休,如何實(shí)現(xiàn)一個(gè)單例類呢?總結(jié)起來玉凯,有以下5種方法實(shí)現(xiàn)一個(gè)單例類势腮。
餓漢式
public class HungrySingleton {
private String content;
private static final HungrySingleton instance = new HungrySingleton();
private HungrySingleton() {
content = "This is a singleton object from hungry type";
}
public static HungrySingleton getInstance() {
return instance;
}
public String getContent() {
return content;
}
}
餓漢式的實(shí)現(xiàn)方式,在類加載的期間壮啊,就已經(jīng)將 instance 靜態(tài)實(shí)例初始化好了嫉鲸,所以,instance 實(shí)例的創(chuàng)建是線程安全的歹啼。不過玄渗,這樣的實(shí)現(xiàn)方式不支持延遲加載實(shí)例。
懶漢式
public class LazySingleton {
private String content;
private static LazySingleton instance;
private LazySingleton() {
content = "This is a singleton object from lazy type";
}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
public String getContent() {
return content;
}
}
懶漢式相對(duì)于餓漢式的優(yōu)勢是支持延遲加載狸眼。這種實(shí)現(xiàn)方式會(huì)導(dǎo)致頻繁加鎖藤树、釋放鎖,以及并發(fā)度低等問題拓萌,頻繁的調(diào)用會(huì)產(chǎn)生性能瓶頸岁钓。
雙重檢查
public class DoubleCheckSingleton {
private String content;
private static volatile DoubleCheckSingleton instance;
private DoubleCheckSingleton() {
content = "This is a singleton object from double-check type";
}
public static DoubleCheckSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckSingleton.class) {
if (instance == null) {
instance = new DoubleCheckSingleton();
}
}
}
return instance;
}
public String getContent() {
return content;
}
}
雙重檢測實(shí)現(xiàn)方式既支持延遲加載、又支持高并發(fā)的單例實(shí)現(xiàn)方式。只要 instance 被創(chuàng)建之后屡限,再調(diào)用 getInstance() 函數(shù)都不會(huì)進(jìn)入到加鎖邏輯中品嚣。所以,這種實(shí)現(xiàn)方式解決了懶漢式并發(fā)度低的問題钧大。
靜態(tài)內(nèi)部類
public class StaticInnerClassSingleton {
private String content;
private StaticInnerClassSingleton() {
content = "This is a singleton object from static inner class type";
}
public String getContent() {
return content;
}
private static class StaticInnerClassSingletonHolder {
private static final StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance() {
return StaticInnerClassSingletonHolder.staticInnerClassSingleton;
}
}
利用 Java 的靜態(tài)內(nèi)部類來實(shí)現(xiàn)單例翰撑。這種實(shí)現(xiàn)方式,既支持延遲加載啊央,也支持高并發(fā)眶诈,實(shí)現(xiàn)起來也比雙重檢測簡單。
枚舉類
public enum EnumSingleton {
INSTANCE;
private String content = "This is a singleton object from enum type";
public String getContent() {
return content;
}
}
最簡單的實(shí)現(xiàn)方式瓜饥,基于枚舉類型的單例實(shí)現(xiàn)逝撬。這種實(shí)現(xiàn)方式通過 Java 枚舉類型本身的特性,保證了實(shí)例創(chuàng)建的線程安全性和實(shí)例的唯一性乓土。
代碼地址
寫在最后
如果你覺得我寫的文章幫到了你宪潮,歡迎點(diǎn)贊、評(píng)論帐我、分享坎炼、贊賞哦,你們的鼓勵(lì)是我不斷創(chuàng)作的動(dòng)力~