執行緒不安全問題主要是由於 uniqueinstance 被例項化多次,採取直接例項化 uniqueinstance 的方式就不會產生執行緒不安全問題。
但是直接例項化的方式也丟失了延遲例項化帶來的節約資源的好處。
public
class
singleton
private
static singleton singleton =
newsingleton()
;}
public
class
singleton
private
static singleton singleton;
public
static singleton getsingleton()
return singleton;
}}
直接加鎖在getsingleton()方法上,會有效能問題,該方法不推薦使用。
public
class
singleton
private
static singleton singleton;
public
static
synchronized singleton getsingleton()
return singleton;
}}
uniqueinstance 只需要被例項化一次,之後就可以直接使用了。加鎖操作只需要對例項化那部分的**進行,只有當 uniqueinstance 沒有被例項化時,才需要進行加鎖。
雙重校驗鎖先判斷 uniqueinstance 是否已經被例項化,如果沒有被例項化,那麼才對例項化語句進行加鎖。
public
class
singleton
private
volatile
static singleton singleton;
public
static singleton getsingleton()
}}return singleton;
}}
uniqueinstance 採用 volatile 關鍵字修飾也是很有必要的, uniqueinstance = new singleton(); 這段**其實是分為三步執行:
1.為 uniqueinstance 分配記憶體空間
2.初始化 uniqueinstance
3.將 uniqueinstance 指向分配的記憶體位址
但是由於 jvm 具有指令重排的特性,執行順序有可能變成 1>3>2。指令重排在單執行緒環境下不會出現問題,但是在多執行緒環境下會導致乙個執行緒獲得還沒有初始化的例項。例如,執行緒 t1 執行了 1 和 3,此時 t2 呼叫 getuniqueinstance() 後發現 uniqueinstance 不為空,因此返回 uniqueinstance,但此時 uniqueinstance 還未被初始化。
使用 volatile 可以禁止 jvm 的指令重排,保證在多執行緒環境下也能正常執行。
當 singleton 類被載入時,靜態內部類 singletonholder 沒有被載入進記憶體。只有當呼叫 getuniqueinstance() 方法從而觸發 singletonholder.instance 時 singletonholder 才會被載入,此時初始化 instance 例項,並且 jvm 能確保 instance 只被例項化一次。
這種方式不僅具有延遲初始化的好處,而且由 jvm 提供了對執行緒安全的支援。
public
class
singleton
private
static singleton singleton;
private
static
class
singletonholder
public
static singleton getsingleton()
}
該實現可以防止反射攻擊。在其它實現中,通過 setaccessible() 方法可以將私有建構函式的訪問級別設定為 public,然後呼叫建構函式從而例項化物件,如果要防止這種攻擊,需要在建構函式中新增防止多次例項化的**。該實現是由 jvm 保證只會例項化一次,因此不會出現上述的反射攻擊。
該實現在多次序列化和序列化之後,不會得到多個例項。而其它實現需要使用 transient 修飾所有字段,並且實現序列化和反序列化的方法。
public
enum singleton
public
void
setobjname
(string objname)
public
static
void
main
(string[
] args)
}catch
(exception e)
}}
簡單工廠把例項化的操作單獨放到乙個類中,這個類就成為簡單工廠類,讓簡單工廠類來決定應該用哪個具體子類來例項化。
這樣做能把客戶類和具體子類的實現解耦,客戶類不再需要知道有哪些子類以及應當例項化哪個子類。客戶類往往有多個,如果不使用簡單工廠,那麼所有的客戶類都要知道所有子類的細節。而且一旦子類發生改變,例如增加子類,那麼所有的客戶類都要進行修改。
public
inte***ce
product
public
class
product1
implements
product
public
class
product2
implements
product
public
class
product2
implements
product
public
class
productfactory
}
簡單工廠的例項化在工廠中實現,工廠方法的例項化在工廠的子類中實現。
public
abstract
class
factory
public calss productfactory1 extends
factory
}public calss productfactory2 extends
factory
}
方法返回null可能出現空指標問題,而且會出現**冗餘。
public
abstract
class
abstractopreation
public nulloperation extend abstractopreation
}public realoperation extend abstractoperation
}public
class
client
public
static abstractoperation func
(int para)
return
newrealoperation()
;}}
CS Notes 筆記的筆記
程序與執行緒 程序同步 同步與互斥 訊號量與互斥量 程序通訊 管道 命名管道 訊息佇列 訊號量共享記憶體 套接字 socket 記憶體管理分頁 分段 分頁與分段inode 資料流重定向1 運算子標準輸入 stdin 0 或 標準輸出 stdout 1 或 標準錯誤輸出 stderr 22 或 2 表...
設計模式學習筆記
1.簡單工廠模式 2.策略模式 3.單一職責原則 就乙個類而言,應該僅有乙個引起它變化的原因 4.開放 封閉原則 就是對軟體實體 類,模組,函式等 應該可以擴充套件,但是不可以修改,無論模組是多麼的 封閉 都會存在一些無法對之的封閉的變化。既然不可能完全封閉,設計人員就必須對他設計的模組應該對哪種變...
設計模式學習筆記
1.單例模式 限制只產生乙個物件。if object null 2.簡單工廠模式 通過乙個工廠類根據條件來建立各種各樣的類。3.工廠方法模式 對工廠類進行改造分解,工廠類公升級為介面,一對一建立工廠類 針對要生產的類 實現工廠介面。問題來了 簡單工廠和工廠方法有什麼優劣?4.迭代器模式 iterat...