版權聲明:本文為部落客原創文章,轉載請标明出處。 https://blog.csdn.net/chaoyu168/article/details/78897883
###定義
保證一個類僅有一個執行個體,并提供一個通路它的全局通路點。
Singleton:負責建立Singleton類自己的唯一執行個體,并提供一個getInstance的方法,讓外部來通路這個類的唯一執行個體。
- 餓漢式:
private static Singleton uniqueInstance = new Singleton();
- 懶漢式
private static Singleton uniqueInstance = null;
###功能 單例模式是用來保證這個類在運作期間隻會被建立一個類執行個體,另外,單例模式還提供了一個全局唯一通路這個類執行個體的通路點,就是getInstance方法。
###範圍 Java裡面實作的單例是一個虛拟機的範圍。因為裝載類的功能是虛拟機的,是以一個虛拟機在通過自己的ClassLoader裝載餓漢式實作單例類的時候就會建立一個類的執行個體。
懶漢式單例有延遲加載和緩存的思想
###優缺點
- 懶漢式是典型的時間換空間
- 餓漢式是典型的空間換時間
- 不加同步的懶漢式是線程不安全的。比如,有兩個線程,一個是線程A,一個是線程B,它們同時調用getInstance方法,就可能導緻并發問題。
- 餓漢式是線程安全的,因為虛拟機保證隻會裝載一次,在裝載類的時候是不會發生并發的。
如何實作懶漢式的線程安全?
加上synchronized即可
public static synchronized Singleton getInstance(){}
但這樣會降低整個通路的速度,而且每次都要判斷。可以用雙重檢查加鎖。
雙重加鎖機制,指的是:并不是每次進入getInstance方法都需要同步,而是先不同步,進入方法過後,先檢查執行個體是否存在,如果不存在才進入下面的同步塊,這是第一重檢查。進入同步塊後,再次檢查執行個體是否存在,如果不存在,就在同步的情況下建立一個執行個體。這是第二重檢查。
雙重加鎖機制的實作會使用一個關鍵字volatile,它的意思是:被volatile修飾的變量的值,将不會被本地線程緩存,所有對該變量的讀寫都是直接操作共享記憶體,進而確定多個線程能正确的處理該變量。
/**
* 雙重檢查加鎖的單例模式
* @author dream
*
*/
public class Singleton {
/**
* 對儲存執行個體的變量添加volitile的修飾
*/
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
//先檢查執行個體是否存在,如果不存在才進入下面的同步塊
if(instance == null){
//同步塊,線程安全的建立執行個體
synchronized (Singleton.class) {
//再次檢查執行個體是否存在,如果不存在才真正的建立執行個體
instance = new Singleton();
}
}
return instance;
}
}
###一種更好的單例實作方式
public class Singleton {
/**
* 類級的内部類,也就是靜态類的成員式内部類,該内部類的執行個體與外部類的執行個體
* 沒有綁定關系,而且隻有被調用時才會裝載,進而實作了延遲加載
* @author dream
*
*/
private static class SingletonHolder{
/**
* 靜态初始化器,由JVM來保證線程安全
*/
private static final Singleton instance = new Singleton();
}
/**
* 私有化構造方法
*/
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
根據《高效Java第二版》中的說法,單元素的枚舉類型已經成為實作Singleton的最佳方法。
package example6;
/**
* 使用枚舉來實作單例模式的示例
* @author dream
*
*/
public class Singleton {
/**
* 定義一個枚舉的元素,它就代表了Singleton的一個執行個體
*/
uniqueInstance;
/**
* 示意方法,單例可以有自己的操作
*/
public void singletonOperation(){
//功能樹立
}
}
###本質 控制執行個體數量
###何時選用單例模式 當需要控制一個類的執行個體隻能有一個,而且客戶隻能從一個全局通路點通路它時,可以選用單例模式,這些功能恰好是單例模式要解決的問題。