標籤:com sdn 反射 實現 comment cts 有一個 code ble
原地址:http://blog.csdn.net/xu__cg/article/details/70182988
Java單例模式是一種常見且較為簡單的設計模式。單例模式,顧名思義一個類僅能有一個執行個體,並且向整個系統提供這一個執行個體。
單例模式的特點:
- 單例類僅能有一個執行個體。
- 單例類必須為自己建立執行個體。
- 單例類必須向外界提供擷取執行個體的方法。
以下是幾種實現方法
一、懶漢式單例(能夠延時載入)
public class SingleTon { private static SingleTon instance = null ; private SingleTon(){ } public static SingleTon getInstance(){ if(instance==null){ instance=new SingleTon(); } return instance ; }}
通過是構造方法私人化使該類不能在外界執行個體化,只能通過public方法擷取執行個體,從而保證執行個體唯一。
但是以上的代碼是線程不安全的,多線程並發的情況下,SingleTon可能產生多個執行個體,可以通過以下方法對getInstance方法進行改進從而保證懶漢式單例安全執行緒。
1.在getInstance()方法上加上同步
public class SingleTon { private static SingleTon instance = null ; private SingleTon(){ } //方法同步,調用效率低! public static synchronized SingleTon getInstance(){ if(instance==null){ instance=new SingleTon(); } return instance ; }}
2.靜態內部類式
public class SingleTon { private static class SingletonClassInstance { private static final SingleTon instance=new SingleTon(); } private SingleTon(){ } //方法沒有同步,調用效率高! public static SingleTon getInstance(){ return SingletonClassInstance.instance ; }}
3.雙重校正鎖式
public class SingleTon { private volatile static SingleTon instance ; private SingleTon(){ } public static SingleTon getInstance(){ if(instance==null){ synchronized(SingleTon.class ){ if(instance==null){ instance=new SingleTon(); } } } return instance ; }}
二、餓漢式單例 (不能夠延時載入)
public class SingleTon { //類初始化時,立即載入這個對象,載入類時,天然的是安全執行緒的! private static SingleTon instance=new SingleTon(); private SingleTon(){ } //方法沒有同步,調用效率高! public static SingleTon getInstance(){ return instance ; }}
餓漢式在類建立的同時就已經建立好一個靜態對象供系統使用,以後不再改變,所以天生是安全執行緒的。
三、枚舉式單例
public enum SingleTon { //這個枚舉元素,本身就是單例對象! INSTANCE; //添加自己需要的操作! public void singletonOperation(){ }}
枚舉式單例是安全執行緒的,調用效率高,並且可以天然的防止反射和還原序列化漏洞。
四、防止反射和還原序列化
事實上,通過Java反射或還原序列化能夠擷取構造方法為private的類執行個體,那麼所有的單例都會失效。所以為了避免這種後果,需要採取相應措施。
/** *懶漢式單例模式(如何防止反射和還原序列化漏洞) * */public class SingleTon implements Serializable { //類初始化時,不初始化這個對象(延時載入,真正用的時候再建立)。 private static SingleTon instance ; private SingleTon(){ //私人化構造器 if(instance!=null){ throw new RuntimeException(); //防止反射 } } //方法同步,調用效率低! public static synchronized SingleTon getInstance(){ if(instance==null){ instance=new SingleTon(); } return instance ; } //還原序列化時,如果定義了readResolve()則直接返回此方法指定的對象。而不需要單獨再建立新對象! private Object readResolve() throws ObjectStreamException { return instance ; } }
五、如何選用單例模式實現方式
- 單例對象佔用資源少,且不需要延時載入:枚舉式 好於 餓漢式
- 單例對象佔用資源大,且需要延時載入:靜態內部類式 好於 一般懶漢式
Java設計模式學習01——單例模式(轉)