目錄html
之前對設計模式沒有太大感受。如今慢慢在工做中愈來愈感受設計模式的重要性,因此決定重頭來好好學習整理下經常使用的設計模式。
本文介紹的最初級的一個設計模式 單例模式java
java中單例模式定義:一個類有且僅有一個實例,而且自行實例化向整個系統提供。設計模式
應用: 一個系統中多線程對一個文件進行操做,這個文件就須要保證只有一個實例,等等安全
說明:餓漢式意思就是不管系統需不須要使用該類的實例對象,先在類加載的時候建立好
優勢:實現簡單
缺點:容易形成內存的浪費多線程
該方式是在該類被加載的時候,就建立好了實例化對象。不容許其餘地方經過構造方法來建立對象,只能經過提供的指定公共方法來獲取惟一的對象。jvm
public class SingletonDemo1 { //static 確保在類加載的時候就會初始化該對象 private final static SingletonDemo1 singleton = new SingletonDemo1(); // 必須是私有構造方法,防止其餘地方經過構造方法來實例化對象 private SingletonDemo1(){ } // 是一個公共的靜態方法,用於對外提供惟一的對象 public static SingletonDemo1 getInstance(){ return singleton; } }
根據枚舉的特性,可使用枚舉來實現單例模式學習
public class SingletonDemo3 { // 不容許其餘地方經過構造方法進行實例化對象 private SingletonDemo3(){} //對外提供可獲取惟一實例化對象的公共方法 public static SingletonDemo3 getInstance(){ return Singleton.SINGLETON.getInstance(); } private enum Singleton{ SINGLETON; private SingletonDemo3 singleton; Singleton(){ singleton = new SingletonDemo3(); } public SingletonDemo3 getInstance(){ return singleton; } } }
說明:懶漢式意思就是在系統第一次須要使用該類的實例對象時,再建立該類的實例對象。
優勢:不形成內存不必的浪費
缺點:實現相對較難.net
在有多線程使用的狀況下不要使用,不然可能會形成建立多個實例對象。通常建議不使用該種方式。線程
public class SingletonDemo1 { //static 確保在類加載的時候就會初始化該對象 private static SingletonDemo1 singleton = null; // 必須是私有構造方法,防止其餘地方經過構造方法來實例化對象 private SingletonDemo1(){ } // 是一個公共的靜態方法,用於對外提供惟一的對象 public static SingletonDemo1 getInstance(){ if(singleton==null){ singleton = new SingletonDemo1(); } return singleton; } }
因爲上面的方式,是在執行getInstance()方法時,多線程使用時可能出現建立多個對象的狀況。那能夠直接將該方法進行同步,保證任意時間,最可能是能一個線程使用該方法。設計
public class SingletonDemo2 { //static 確保在類加載的時候就會初始化該對象 private static SingletonDemo2 singleton = null; // 必須是私有構造方法,防止其餘地方經過構造方法來實例化對象 private SingletonDemo2(){ } // 是一個公共的靜態方法,用於對外提供惟一的對象 public static synchronized SingletonDemo2 getInstance(){ if(singleton==null){ singleton = new SingletonDemo2(); } return singleton; } }
缺點:過重了,每一個線程在每次使用的時候,都須要進行同步,而實際上只是在第一次獲取該類的實例對象時須要同步,日後使用不須要同步。
該方式只會在未實例化對象時,才同步進行實例化對象。實例化後就不須要再進行同步了。
public class SingletonDemo2 { //static 確保在類加載的時候就會初始化該對象 private static volatile SingletonDemo2 singleton = null; // 必須是私有構造方法,防止其餘地方經過構造方法來實例化對象 private SingletonDemo2(){ } // 是一個公共的靜態方法,用於對外提供惟一的對象 public static SingletonDemo2 getInstance(){ if(singleton==null){ synchronized (SingletonDemo2.class){ if(singleton==null) { //爲了防止多個線程進行實例化 singleton = new SingletonDemo2(); } } } return singleton; } }
有麼有注意到,使用了volatitle關鍵字,爲何要使用volatile關鍵字?
答:這裏使用了volatile一個重要的特性——禁止JVM指令重排序
singleton = new SingletonDemo2()的在jvm內存中會有三步,1)分配內存;2)初始化對象;3)將對象指向分配的內存。jvm在會在不改變最終執行結果的狀況下對指令進行重排序,即:可能執行順序是1->3->2,如果在執行執行3還未執行2時,其餘線程執行使用,則會報錯。
(參考:http://www.javashuo.com/article/p-plwggyio-cp.html)
http://www.javashuo.com/article/p-qjktkfot-ck.html
http://www.runoob.com/design-pattern/singleton-pattern.html
java實例化對象過程說明:http://www.javashuo.com/article/p-rtbvcfpv-ey.html