自學MYSQL第30天!
阿新 • • 發佈:2021-07-01
單例模式(建立型模式)
基本介紹
單例模式指在整個應用中,某個類只存在一個例項物件,且該類只提供一個取得其物件例項的方法。
應用
JDK的Runtime中使用到了餓漢式單例模式
單例模式的八種方式
(1)餓漢式(靜態常量)
(2)餓漢式(靜態程式碼塊)
(3)懶漢式(執行緒不安全)
(4)懶漢式(執行緒安全,同步方法)
(5)懶漢式(執行緒安全,同步程式碼塊)
(6)雙重檢查
(7)靜態內部類
(8)列舉
餓漢式(靜態常量)(可以使用)
程式碼實現
//餓漢式(靜態常量) public class Hunger { private Hunger(){ } private static final Hunger instance=new Hunger(); public static Hunger getInstance(){ return instance; } }
優缺點
-
優點:寫法簡單,類載入時完成了例項化,避免了執行緒同步問題。
-
缺點:類載入時完成了例項化,沒達到lazy loading(惰性載入)的效果,若從不會用到這個例項會造成記憶體浪費。
原因:不一定是通過呼叫getInstance()方法導致類載入,有可能是其他的方式導致類載入
-
總結:這種單例模式可用,可能造成記憶體浪費。
餓漢式(靜態程式碼塊)(可以使用)
程式碼實現
//餓漢式(靜態程式碼塊) public class Hunger { private Hunger(){ } private static Hunger instance; static { instance=new Hunger(); } public static Hunger getInstance(){ return instance; } }
優缺點
同上述靜態屬性的優缺點
懶漢式(執行緒不安全)
程式碼實現
public class Lazy {
private Lazy(){
}
private static Lazy instance;
public static Lazy getInstance() {
if(instance==null){
instance=new Lazy();
}
return instance;
}
}
優缺點
- 優點:起到了lazy loading的效果,但只能在單執行緒下使用,
- 缺點:在多執行緒下可能產生多個例項,多執行緒不安全
- 結論:實際開發中不建議使用。
懶漢式(執行緒安全,同步方法)
程式碼實現
//懶漢式(執行緒安全)
public class Lazy {
private Lazy(){
}
private static Lazy instance;
//加入同步處理程式碼,解決執行緒不安全問題
public static synchronized Lazy getInstance() {
if(instance==null){
instance=new Lazy();
}
return instance;
}
}
優缺點
- 優點:解決了執行緒不安全問題
- 缺點:效率低,每個執行緒想要獲得類的例項時,執行getInstance()方法都要進行同步,
- 實際開發時不推薦使用
懶漢式(執行緒安全,同步程式碼塊)
程式碼實現
//懶漢式(執行緒安全)
public class Lazy {
private Lazy(){
}
private static Lazy instance;
public static Lazy getInstance() {
if(instance==null){
//此處加入了同步程式碼塊,當兩執行緒都進入了判斷語句,還是有可能造成兩個例項的產生。
synchronized (Lazy.class){
instance=new Lazy();
}
}
return instance;
}
}
優缺點
- 這種方法本意是對懶漢式同步方法的改進,因為懶漢式同步方法的效率太低。將其更改為同步產生例項的程式碼塊
- 但這種同步方法並不能起到執行緒同步的作用,只要兩個執行緒都進入了判斷語句,還是有可能產生多個例項。
- 實際開發中不使用。
雙重檢查(推薦使用)
程式碼實現
//雙重檢測(執行緒安全)
public class Lazy {
private Lazy(){
}
//volatile:保證了一致性,不保證原則性,防止指令重拍
private volatile static Lazy instance;
public static Lazy getInstance() {
if(instance==null){
//加入同步程式碼塊
synchronized (Lazy.class){
//進行第二次檢測
if(instance==null){
instance=new Lazy();
}
}
}
return instance;
}
}
優缺點
- Double-Check概念是多執行緒開發中經常使用的,進行了兩次if(instance==null)檢查,保證了執行緒安全。
- 這樣的設計使得例項化程式碼只執行一次:後面的·1訪問都是直接return例項化物件,避免反覆進行方法同步。
- 優點:執行緒安全,延遲載入,效率較高,
- 結論:實際開發中建議使用。
靜態內部類(推薦使用)
程式碼實現
//靜態內部類(執行緒安全)
public class Lazy {
private Lazy(){
}
public static Lazy getInstance(){
return inner.INSTANCE;
}
static class inner{
private static final Lazy INSTANCE=new Lazy();
}
}
優缺點
- 採用了類裝載的機制保證了初始化例項時,只有一個執行緒。
- 靜態內部類方法在此類被載入時不會立即例項化,只有在呼叫getInstance()方法時才會載入其內部類並完成此類的例項化。
- 類的靜態屬性只會在第一次載入類時初始化,此處,JVM幫助我們保證了執行緒的安全性。類初始化時,別的執行緒無法進入。
- 優點:避免了執行緒不安全,使用靜態內部類的特點實現了延遲載入,效率高。
- 結論:推薦使用。
列舉(推薦使用)
程式碼實現
public enum Singleton {
INSTANCE;//屬性
public void sayOk(){
System.out.println("ok~~");
}
}
優缺點
- 優點:借用列舉來實現單例模式,不僅能避免多執行緒同步問題,而且可以防止反序列化重新建立新的物件。
- 結論:推薦使用
注意事項
- 單例模式保證了系統記憶體中該類只存在一個物件,節省了系統資源,對於一些需要頻繁建立銷燬的物件,使用單例模式可以提高系統性能。
- 要例項化一個單例類時,使用相應獲取物件的方法而不是new();
- 單例模式使用場景:需要頻繁進行建立或銷燬的物件;建立物件時耗時過多或耗費資源過多(重量級物件)且經常使用的物件,工具類物件,頻繁訪問資料庫或檔案的物件(如:資料來源,session工廠等 )