Mybatis學習---第一個查詢小程式
一、什麼是單例模式
單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立(私有的構造器),這個類對外提供了唯一一種訪問其例項的方式,對外只能夠直接訪問,不能例項化此類物件。例如,一臺計算機上可以連線多臺印表機,但是這個計算機上的列印程式只能有一個,這裡就可以通過單例模式來避免兩個列印作業同時輸出到印表機中,即在整個的列印過程中只有一個列印程式的例項。
簡單點說,單例模式(也叫單件模式)的作用就是保證在整個應用程式的生命週期中,任何時刻,單例類的例項都最多隻存在一個。單例模式確保某一個類只有一個例項,而且自行例項化,並向整個系統提供這個例項單例模式。單例模式只應在有真正的“單一例項”需求時才可以使用。單例的類圖如下:
二、8 種單例實現方式
【1】餓漢式(靜態常量)優缺點:
● 優點:這種寫法比較簡單,就是在類裝載的時候就完成例項化。避免了執行緒同步問題。沒有加鎖,執行效率會提高。
● 缺點:在類裝載的時候就完成例項化,沒有達到 Lazy Loading 的效果。如果從始至終從未使用過這個例項,則會造成記憶體浪費,容易產生垃圾物件。
● 這種方式基於 classload 機制避免了多執行緒同步問題,instance 在類裝載時就例項化,在單例模式中大多數都是呼叫 getInstance 方法,但是導致類裝載的原因有很多種,因此通過其他方式(或者其他靜態方法)導致類裝載,此時初始化 instance就沒有達到 Lazy Loading 的效果。
1 public class SingleTon { 2 //將構造器私有化,防止直接 New 3 private SingleTon(){} 4 5 //建立好一個私有的 SingleTon 例項 6 private static SingleTon instance = new SingleTon(); 7 8 //提供一個 public 的靜態方法, 可以返回 instance 9 public static SingleTon getInstance() { 10 return instance;11 } 12 }
【2】餓漢式(靜態程式碼塊)優缺點:
● 這種方式和上面的方式其實類似,只不過將類例項化的過程放在了靜態程式碼塊中,也是在類裝載的時候,就執行靜態程式碼塊中的程式碼,初始化類的例項。優缺點和上面一樣。
● 結論:這種單例模式可用,但可能造成記憶體浪費。
1 public class SingleTon { 2 //將構造器私有化,防止直接 New 3 private SingleTon(){} 4 5 //建立好一個私有的 SingleTon 例項 6 private static SingleTon instance; 7 //靜態塊 8 static { 9 instance = new SingleTon(); 10 } 11 12 //提供一個 public 的靜態方法, 可以返回 instance 13 public static SingleTon getInstance() { 14 return instance; 15 } 16 }
【3】懶漢式(執行緒不安全)優缺點:
● 起到了 Lazy Loading 的效果,但是隻能在單執行緒下使用。
● 如果在多執行緒下,一個執行緒進入if(singleton == null)判斷語句塊,還未來得及建立,另一個執行緒也通過了上述判斷語句,這時便產生了多個例項。所以在多執行緒環境下不可使用這種方式。
● 結論:在實際開發中,不要使用這種方法。
1 public class SingleTon { 2 //將構造器私有化,防止直接 New 3 private SingleTon(){} 4 5 //建立好一個私有的 SingleTon 例項 6 private static SingleTon instance; 7 8 //提供一個 public 的靜態方法, 可以返回 instance 9 public static SingleTon getInstance() { 10 if(instance == null) { 11 instance = new SingleTon(); 12 } 13 return instance; 14 } 15 }
【4】懶漢式(執行緒安全,同步方法)優缺點:
● 解決了執行緒不安全問題。
● 效率太低了,每個執行緒在想獲得類的例項的時候,執行 getInstance() 方法都要進行同步。而其實這個方法只執行一次例項化程式碼就夠了,後面的想獲得例項,直接 return 就夠了。方法進行同步效率太低。
● 結論:在實際開發中不推薦使用。
1 public class SingleTon { 2 //將構造器私有化,防止直接 New 3 private SingleTon(){} 4 5 //建立好一個私有的 SingleTon 例項 6 private static SingleTon instance; 7 8 //提供一個 public 的靜態方法, 可以返回 instance 9 public static synchronized SingleTon getInstance() { 10 if(instance == null) { 11 instance = new SingleTon(); 12 } 13 return instance; 14 } 15 }
【5】懶漢式(執行緒安全,同步程式碼塊)優缺點:
● 這種方式,本意是想對第四種實現方式的改進,因為前面同步方法效率太低, 改為同步產生例項化的的程式碼塊。
● 但是這種同步並不能起到執行緒同步的作用。跟第3種實現方式遇到的情形一致,假如一個執行緒進入了 if (singleton == null) 判斷語句塊,還未來得及往下執行,另一個執行緒也通過了這個判斷語句,這時便會產生多個例項。
● 結論:在實際開發中,不能使用這種方式。
1 public class SingleTon { 2 //將構造器私有化,防止直接 New 3 private SingleTon(){} 4 5 //建立好一個私有的 SingleTon 例項 6 private static SingleTon instance; 7 8 //提供一個 public 的靜態方法, 可以返回 instance 9 public static SingleTon getInstance() { 10 if(instance == null) { 11 //新增同步程式碼塊,提高了效率,多執行緒時存在建立的物件不一致風險 12 synchronized(SingleTon.class) { 13 instance = new SingleTon(); 14 } 15 } 16 return instance; 17 } 18 }
【6】雙重檢查(Double-Check)優缺點:
● 雙重檢查概念是多執行緒開發中常使用到的,如程式碼所示,我們進行了兩次 if(instance == null) 檢查,這樣就確保了執行緒的安全,同時也提高了效率。
● 這樣,例項化程式碼只用執行一次,後面再次訪問時,判斷 if(instance == null) , 直接 return 例項化物件,也避免的反覆進行方法同步。
● 執行緒安全;延遲載入;效率較高。
● 結論:在實際開發中,推薦使用這種單例設計模式。
1 public class SingleTon { 2 //將構造器私有化,防止直接 New 3 private SingleTon(){} 4 5 //建立好一個私有的 SingleTon 例項 6 private static volatile SingleTon instance; 7 8 //提供一個 public 的靜態方法, 可以返回 instance 9 public static SingleTon getInstance() { 10 //新增同步程式碼塊,提高了效率. 11 if(instance == null) { 12 synchronized(SingleTon.class) { 13 //解決多執行緒可能建立多個例項的情況 14 if(instance == null) { 15 instance = new SingleTon(); 16 } 17 } 18 } 19 return instance; 20 } 21 }
【7】靜態內部類優缺點:
● 這種方式採用了類載入器的機制來保證初始化例項時只有一個執行緒。
● 靜態內部類方式在 SingleTon 類(父類)被裝載時,不會導致內部類被裝載,也就不會立即例項化,屬於懶載入型別。當呼叫 getInstance() 方法時,才會裝載 SingleTonInstance 類,從而完成 SingleTon 的例項化。
● 類的靜態屬性只會在第一次載入類的時候初始化,所以在這裡,JVM 幫我們保證了執行緒的安全,在類初始化時,別的執行緒無法進入。
● 避免了執行緒不安全,利用靜態內部類特點實現延遲載入,效率高 。
● 結論:推薦使用。
1 public class SingleTon { 2 //將構造器私有化,防止直接 New 3 private SingleTon(){} 4 5 //在內部內中建立一個物件的例項,當父類 SingleTon 載入時,內部類 SingleTonInstance 無需載入 6 private static class SingleTonInstance{ 7 private static final SingleTon INSTANCE = new SingleTon(); 8 } 9 10 //提供一個 public 的靜態方法, 可以返回 SingleTon例項 11 public static SingleTon getInstance() { 12 return SingleTonInstance.INSTANCE; 13 } 14 }
【8】列舉優缺點:
● 這藉助JDK1.5中新增的列舉來實現單例模式。不僅能避免多執行緒同步問題,而且還能防止反序列化重新建立新的物件。
● 這種方式是Effective Java作者Josh Bloch 提倡的方式
● 結論:推薦使用
enum SingleTon { //當只有一個物件時,就是單例 INSTANCE; }
三、單例模式注意事項和細節
【1】單例模式保證了系統記憶體中該內只存在一個物件,節省了系統資源,對於一些需要頻繁建立和銷燬的物件,使用單例模式可以提高系統性能。
【2】當想例項化一個單例類的時候,必須要記住使用相應的獲取物件的方法,而不是使用 new。
【3】單例模式使用場景:需要頻繁的進行建立和銷燬物件、建立物件時耗時過多或消耗過多資源(既重量級物件)但有常使用的物件、工具類物件、頻繁訪問資料庫或檔案的物件(比如資料來源、session工廠等)。----如果喜歡,點個紅心♡支援以下,謝謝