設計模式之單例模式實踐
阿新 • • 發佈:2018-11-14
概念
單例模式即一個JVM記憶體中只存在一個類的物件例項
分類
1、懶漢式
類載入的時候就建立例項
2、餓漢式
使用的時候才建立例項
當然還有其他的生成單例的方式,雙重校驗鎖,列舉和靜態內部類,文中會有介紹
實踐
懶漢式
1)執行緒不安全,不可用
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
2)執行緒安全,同步方法,效率低,不推薦
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
3)執行緒不安全,會產生多個例項,不可用
public class Singleton { private static Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { singleton = new Singleton(); } } return singleton; } }
4) 餓漢式,無執行緒安全問題,不能延遲載入,影響系統性能
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
5)
public class Singleton {
private static Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
6)雙重校驗鎖,執行緒安全,推薦使用
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
7)靜態內部類,執行緒安全,主動呼叫時才例項化,延遲載入效率高,推薦使用
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
8)列舉型別,無執行緒安全問題,避免反序列華建立新的例項,很少使用
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
注意事項
1、考慮多執行緒問題
2、單例類構造方法要設定為private型別禁止外界new建立
private Singleton() {}
3、如果類可序列化,考慮反序列化生成多個例項問題,解決方案如下
private Object readResolve() throws ObjectStreamException {
// instead of the object we're on, return the class variable INSTANCE
return INSTANCE;
}
使用場景
1、工具類物件
2、系統中只能存在一個例項的類
3、建立頻繁或又耗時耗資源且又經常用到的物件
下面是單例模式在JDK的應用
另外,spring容器中的例項預設是單例餓漢式型別的,即容器啟動時就例項化bean到容器中,當然也可以設定懶漢式defalut-lazy-init="true"為延遲例項化,用到時再例項化。