單例模式指的是在內存中只有一個對象 ,這樣咱們想到實現單例模式應該用到static關鍵字多線程
一 懶漢式單例函數
先看下面這個類測試
//懶漢式單例類(我是沒明白這個命名是怎麼來的 與後面的餓漢式單例 的區別是 實例域初始化的時間) public class Singleton { //私有構造方法 通常構造方法都是public 私有說明不能在這個類的外部實例化這個類 private Singleton(){} private static Singleton single=null; //靜態工廠方法 public static Singleton getInstance(){ if (single == null) { single = new Singleton(); } return single; } public static void main(String args[]) { Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); } }
首先看到這個類的結構 線程
這個類只有一個域 這個域是引用類型 這個域被static 修飾 會在類編譯的時候就加載 只不過這個時候是nullcode
有兩個靜態方法 另一個main方法是我測試用的對象
打印出的結果是true 說明兩個對象是同一個對象內存
private Singleton() {}; 構造函數 跟類名相同的方法是構造函數 構造函數是用來構造一個類的 構造函數通常是public 能夠在類外調用 這裏變成private 就能夠防止在另一個類裏面用new的方式建立了 咱們能夠試試在另一個類裏嗎調用這個構造函數 public static void main(String[] args) { // TODO Auto-generated method stub Singleton singleton = new Singleton(); } 編譯是報錯的
咱們經過 類名.方法 的方式調用靜態類開發
Singleton.getInstance(); 若是實例域是null(第一個調用這個方法)則建立實例域(經過私有構造函數)
2、餓漢式單例get
public class Singleton { private Singleton() {} private static final Singleton single = new Singleton(); //靜態工廠方法 public static Singleton getInstance() { return single; } public static void main(String args[]) { Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance == instance2); } }
與上面的懶漢式區別是靜態實例域一開始就構造出來了 而懶漢式開始加載的時候是null編譯
也就是餓漢式每次調用時都是同一個對象 類編譯的時候就經過new Singleton() 的方式構造出來 並且在後面不可改變
三 靜態內部類方式
public class Singleton { private Singleton() {//構造函數 } private static class innerClass{ //靜態內部類 編譯後就成了一個單獨的類 Singleton$innerClass public static final Singleton instance = new Singleton() ; } public static final Singleton getinstance(){ return innerClass.instance; } public static void main(String[] args) { // TODO Auto-generated method stub Singleton instance = Singleton.getinstance(); Singleton instance1 = Singleton.getinstance(); System.out.println(instance == instance1); } }
調用單例的方法一樣是 類名.方法 經過內部類的方式調用就是 單例類一開始就構造出來了這跟餓漢式是同樣的 只不過是在內部類中構造的 。
這三個例子都只是實現了單例模式的基本結構 在實際開發中咱們應當在構造函數中實現更多的方法。
另外 網上有不少關於多線程與單例的討論 我只知道第2、三種方法構造出來的單例對象在程序中是不能從新改變賦值的
有朋友瞭解這方面的問題的能夠說下哈