它存在的目的是可以限制物件(Object)產生的數量,只容許產生一個物件(Objest)。
那就是只有一個實例(Instance)。
往後每次調用都是指向相同的物件(Object)。
public class Singleton{
private static Singleton uniqueInstance;
// 使用private Consructor 確保類別Singleton 的物件(Object)只能透過 API – method : getInstance()。
private Singleton()
{
// 這裡可以有很多code,所以建立物件(Object)可能需要很多資源/時間。
}
// 因為Constructor已經private,所以需要以下方法讓其他程式調用這個類別。
public static Singleton getInstance() {
// 第一次被呼叫時,才建立物件(Object)
if(uniqueInstance == null ) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
以上程式在某些情況運行時是沒問題,但如果是在多執行緒(Multi Thread)的情況下呼叫getInstance(),可能第一個執行緒(Thread)跑到instance = new Singleton()時,另一個執行緒(Thread)在 if(uniqueInstance==null) 判斷時也進入迴圈(loop), 最後同一時間產生了多於一個的物件(Object)。
為了解決這個情況,我們需要對剛才的程式進行修改。
在程式內加上同步(synchronized)關鍵字
public class Singleton{
private static Singleton uniqueInstance;
// 使用private Consructor 確保類別Singleton 的物件(Object)只能透過 API – method : getInstance()。
private Singleton()
{
// 這裡可以有很多code,所以建立物件(Object)可能需要很多資源/時間。
}
// 因為Constructor已經private,所以需要以下方法讓其他程式調用這個類別。
public static synchronized Singleton getInstance() {
// 使用 synchronized 關鍵字避免多於一個Thread 進入
if(uniqueInstance == null ) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
不過同步(synchronized)關鍵字會導致程式的執行效能會變差,(不適合用於像伺服器這種有很多執行緒(Multi Thread)的程式上)。
所以可以使用雙重檢查鎖定模式(Double-check Locking),加快程式的效能。
雙重檢查鎖定模式(Double-check Locking)
就是將synchronized搬到getInstance方法內。
public class Singleton{
private static Singleton uniqueInstance;
// 使用private Consructor 確保類別Singleton 的物件(Object)只能透過 API – method : getInstance()。
private Singleton()
{
// 這裡可以有很多code,所以建立物件(Object)可能需要很多資源/時間。
}
// 因為Constructor已經private,所以需要以下方法讓其他程式調用這個類別。
public static Singleton getInstance() {
// 使用 synchronized 關鍵字避免多於一個Thread 進入
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
} return uniqueInstance;
}
}