java的單例模式
java單例模式
意義: 確保某個類有且只有一個實例。避免產生多個對象消耗過多的資源,或者某種類型的對象只應該有且既有一個。
例如創建一個對象需要消耗資源過多,如要訪問IO和數據庫資源、網絡資源,這事就要考慮使用單例
特點: (1)構造方法私有化,一般爲private
(2)通過一個靜態方法返回單例對象。
(3)確保單例類對象只有一個,尤其是在多線程的情況下。
(4)確保單例類對象在反序列化時,不重新構建對象。
1 懶漢式單列模式
優點:單例只有在使用的時候纔會初始化化,在一定程度上節約了資源。
缺點:第一次加載時需要及時的進行初始化,反應稍微慢,最大的問題是每次調用getInstanse
private static Singleton instance;
private Singleton()
{
}
public static Singleton getInstance()
{
if(instance==null)
{
instance=new Singleton();
}
return instance;
}
2 餓漢式單列模式
這種方式基於classloader機制避免了多線程的同步問題,不過,instance在類裝載時就實例化
private static Singleton instance=new Singleton();
private Singleton()
{
}
public static Singleton getInstance()
{
return instance;
}
3 雙重檢查(不推薦)
爲處理原版非延遲加載方式瓶頸問題,我們需要對 instance 進行第二次檢查,目的是避開過多的同步(因爲這裏的同步只需在第一次創建實例時才同步,一旦創建成功,以後獲取實例時就不需要同獲取鎖了),但在Java中行不通,因爲同步塊外面的if (instance == null)可能看到已存在,但不完整的實例
private static Singleton instance;
private Singleton()
{
}
public static Singleton getInstance()
{
if(instance==null)
{
synchronized (Singleton.class)//高併發狀態下上一種很容易產生多個實例,所以我們 需要尋找線程安全的方法,首先最容易就是添加synchronized關鍵字
{
if(instance==null)
{
instance=new Singleton();
}
}
}
return instance;
}
4 內部靜態類(安全 推薦)
由於內部靜態類只會被加載一次,故該實現方式時線程安全的!
private Singleton()
{
}
public static Singleton getInstance()
{
return Nested.instance;
}
static class Nested
{
private static Singleton instance = new Singleton();
}
這種方式同樣利用了classloder的機制來保證初始化instance時只有一個線程,它跟餓漢不同的是(很細微的差別)餓漢是隻要Singleton類被裝載了,那麼instance就會被實例化(沒有達到lazy loading效果),而這種方式是Singleton類被裝載了,instance不一定被初始化。因爲SingletonHolder類沒有被主動使用,只有顯示通過調用getInstance方法時,纔會顯示裝載SingletonHolder類,從而實例化instance。想象一下,如果實例化instance很消耗資源,我想讓他延遲加載,另外一方面,我不希望在Singleton類加載時就實例化,因爲我不能確保Singleton類還可能在其他的地方被主動使用從而被加載,那麼這個時候實例化instance顯然是不合適的。這個時候,這種方式相比餓漢就顯得很合理。
5 枚舉 (推薦)
public enum Singleton
{
instance;
public void operate(){}
} //直接調用Singleton.instance;
這種方式是Effective Java作者Josh Bloch 提倡的方式,它不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象,可謂是很堅強的壁壘啊,不過,個人認爲由於1.5中才加入enum特性,用這種方式寫不免讓人感覺生疏,在實際工作中,我也很少看見有人這麼寫過。
意義: 確保某個類有且只有一個實例。避免產生多個對象消耗過多的資源,或者某種類型的對象只應該有且既有一個。
例如創建一個對象需要消耗資源過多,如要訪問IO和數據庫資源、網絡資源,這事就要考慮使用單例
特點: (1)構造方法私有化,一般爲private
(2)通過一個靜態方法返回單例對象。
(3)確保單例類對象只有一個,尤其是在多線程的情況下。
(4)確保單例類對象在反序列化時,不重新構建對象。
1 懶漢式單列模式
優點:單例只有在使用的時候纔會初始化化,在一定程度上節約了資源。
缺點:第一次加載時需要及時的進行初始化,反應稍微慢,最大的問題是每次調用getInstanse
private static Singleton instance;
private Singleton()
{
}
public static Singleton getInstance()
{
if(instance==null)
{
instance=new Singleton();
}
return instance;
}
2 餓漢式單列模式
這種方式基於classloader機制避免了多線程的同步問題,不過,instance在類裝載時就實例化
private static Singleton instance=new Singleton();
private Singleton()
{
}
public static Singleton getInstance()
{
return instance;
}
3 雙重檢查(不推薦)
爲處理原版非延遲加載方式瓶頸問題,我們需要對 instance 進行第二次檢查,目的是避開過多的同步(因爲這裏的同步只需在第一次創建實例時才同步,一旦創建成功,以後獲取實例時就不需要同獲取鎖了),但在Java中行不通,因爲同步塊外面的if (instance == null)可能看到已存在,但不完整的實例
private static Singleton instance;
private Singleton()
{
}
public static Singleton getInstance()
{
if(instance==null)
{
synchronized (Singleton.class)//高併發狀態下上一種很容易產生多個實例,所以我們 需要尋找線程安全的方法,首先最容易就是添加synchronized關鍵字
{
if(instance==null)
{
instance=new Singleton();
}
}
}
return instance;
}
4 內部靜態類(安全 推薦)
由於內部靜態類只會被加載一次,故該實現方式時線程安全的!
private Singleton()
{
}
public static Singleton getInstance()
{
return Nested.instance;
}
static class Nested
{
private static Singleton instance = new Singleton();
}
這種方式同樣利用了classloder的機制來保證初始化instance時只有一個線程,它跟餓漢不同的是(很細微的差別)餓漢是隻要Singleton類被裝載了,那麼instance就會被實例化(沒有達到lazy loading效果),而這種方式是Singleton類被裝載了,instance不一定被初始化。因爲SingletonHolder類沒有被主動使用,只有顯示通過調用getInstance方法時,纔會顯示裝載SingletonHolder類,從而實例化instance。想象一下,如果實例化instance很消耗資源,我想讓他延遲加載,另外一方面,我不希望在Singleton類加載時就實例化,因爲我不能確保Singleton類還可能在其他的地方被主動使用從而被加載,那麼這個時候實例化instance顯然是不合適的。這個時候,這種方式相比餓漢就顯得很合理。
5 枚舉 (推薦)
public enum Singleton
{
instance;
public void operate(){}
} //直接調用Singleton.instance;
這種方式是Effective Java作者Josh Bloch 提倡的方式,它不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象,可謂是很堅強的壁壘啊,不過,個人認爲由於1.5中才加入enum特性,用這種方式寫不免讓人感覺生疏,在實際工作中,我也很少看見有人這麼寫過。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.