摘要:簡介最基本的實例中規定了一個類只會被初始化一次所以該方法是線程安全的但是其在方法調用前就初始化了比較浪費資源優點只有一個實例節約內存空間減少了系統的性能開銷如果某一個對象的產生需要比較多的資源時可以在啟動時直接產生一個單例對象使其永駐內存可
In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects. The term comes from the mathematical concept of a singleton簡介 最基本的實例
public class Emperor { private static final Emperor emperor=new Emperor(); private Emperor(){} public static Emperor getInstance(){ return emperor; } }
Java Language Specification 中規定了一個類只會被初始化一次.所以該方法是線程安全的, 但是其在方法調用前就初始化了, 比較浪費資源.
優點只有一個實例, 節約內存空間, 減少了系統的性能開銷, 如果某一個對象的產生需要比較多的資源時, 可以在啟動時直接產生一個單例對象, 使其永駐內存.
可以避免對資源的多重占用,
可以在系統設置全局的訪問點, 優化和共享資源訪問.
缺點單例模式一般沒有接口, 擴展很困難, 除了修改代碼基本上沒有第二種途徑可以實現
單例模式不利于測試, 如果單例模式沒有完成, 無法進行測試
與單一職責原則相沖突.
其它實現方式 懶漢模式class Singleton { private static Singleton instance; private Singleton(){} public static synchronized Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; } }
該實現只會在需要的時候才會進行初始化且是線程安全的, 但是每次調用getInstance()都會進行同步, 會浪費資源
Double Check Lockclass SingletonDCL{ private static SingletonDCL sInstance; private SingletonDCL(){} public static SingletonDCL getInstance(){ if(sInstance==null){ synchronized (SingletonDCL.class){ if(sInstance==null){ sInstance=new SingletonDCL(); } } } return sInstance; } }
該實現只會在需要的時候才會進行初始化, 看似線程安全, 但實際并不是.
假設線程A執行到sInstance=new SingletonDCL(), 這句代碼并不是一個原子操作, 這句代碼大致會被分為下面3個步驟來處理:
給SingletonDCL的實例分配內存
調用SingletonDCL的構造函數, 初始化成員字段
將sInstance對象指向分配的內存空間 (此時sInstance就不是null了).
如果這句代碼嚴格按照這個順序執行,該DCL單例模式便是線程安全的, 但是事實并非如此. 原因是JVM并沒有保證上述第2和第3步的執行順序.
也就是說執行步驟可能是1-3-2, 這種執行步驟就會出問題:
當先執行第3步時, 另一個線程B開始執行getInstance(), 由于此時sInstance已經不是null了, 所以線程B會返回一個還未初始化的sInstance, 出現了錯誤.
JVM1.5之后改善了這個問題, 在sInstance前加上volatile關鍵字可以確保線程安全.
即private static volatile SingletonDCL sInstance;
DCL單例模式并不推薦使用,《Java并發編程實踐》推薦使用下面這個方法:
class SingletonStatic{ private SingletonStatic(){} public static SingletonStatic getInstance(){ return SingletonStaticHolder.sInstance; } private static class SingletonStaticHolder{ private static final SingletonStatic sInstance=new SingletonStatic(); } }
第一次加載時, 并不會初始化sInstance, 只在第一調用getInstance()時初始化, 且該方法是線程安全的.
枚舉單例enum SingletonEnum{ INSTACNE; public void doSomething(){ StdOut.println("doSomething..."); } }
枚舉單例模式有以下3個優點:
線程安全, 任何時候都只有一個實例
反序列化時, 都只會有一個實例
可以防止反射攻擊
選擇哪一種實現方式無論采用哪一種實現方式, 都要確保線程安全, 防止反序列化導致重新生成實例對象等一些問題. 具體選擇哪一種實現方式取決于項目本身.
關于序列化除了枚舉單例, 為了避免單例對象在被反序列化時重新生成對象, 必須加入以下方法
private Object readResolve() throws ObjectStreamException{ return sInstance; }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71722.html
摘要:總結單例是運用頻率很高的模式,因為客戶端沒有高并發的情況,選擇哪種方式并不會有太大的影響,出于效率考慮,推薦使用和靜態內部類實現單例模式。 單例模式介紹 單例模式是應用最廣的模式之一,也可能是很多人唯一會使用的設計模式。在應用單例模式時,單例對象的類必須保證只用一個實例存在。許多時候整個系統只需要一個全局對象,這樣有利于我么能協調整個系統整體的行為。 單例模式的使用場景 確保某個類有且...
摘要:不符合設計模式中的單一職責的概念。引入代理實現單例模式引入代理實現單例模式的特點我們負責管理單例的邏輯移到了代理類中。的單例模式對比在以上的代碼中實現的單例模式都混入了傳統面向對象語言的特點。 聲明:這個系列為閱讀《JavaScript設計模式與開發實踐》 ----曾探@著一書的讀書筆記 1.單例模式的特點和定義 保證一個類僅有一個實例,并且提供一個訪問它的全局訪問點。 2.傳統面向對...
摘要:但是,這并不是采用單例的唯一原因。使用命名空間單例模式也被稱為模塊設計模式。函數內部聲明了一些局部函數和或變量。緊隨函數聲明放置即可立即執行外部函數,并將所得的對象文字費賠給變量。 JavaScript設計模式-第一部分:單例模式、組合模式和外觀模式 設計模式是一些可靠的編程方式,有助于保證代碼更加易于維護、擴展及分離,所有設計模式在創建大型JavaScript應用程序時均不可或缺 單...
摘要:如果需要防范這種攻擊,請修改構造函數,使其在被要求創建第二個實例時拋出異常。單例模式與單一職責原則有沖突。源碼地址參考文獻設計模式之禪 定義 單例模式是一個比較簡單的模式,其定義如下: 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 或者 Ensure a class has only one instance, and provide a global point of ac...
摘要:在設計模式一書中,將單例模式稱作單件模式。通過關鍵字,來保證不會同時有兩個線程進入該方法的實例對象改善多線程問題為了符合大多數程序,很明顯地,我們需要確保單例模式能在多線程的情況下正常工作。 在《Head First 設計模式》一書中,將單例模式稱作單件模式。這里為了適應大環境,把它稱之為大家更熟悉的單例模式。 一、了解單例模式 1.1 什么是單例模式 單例模式確保一個類只有一個實例,...
閱讀 2570·2021-11-23 09:51
閱讀 3120·2019-08-30 15:54
閱讀 1070·2019-08-30 14:14
閱讀 3542·2019-08-30 13:59
閱讀 1393·2019-08-29 17:09
閱讀 1468·2019-08-29 16:24
閱讀 2848·2019-08-29 15:43
閱讀 911·2019-08-29 12:45