Java設計模式之單例模式簡單解析
單例模式的優(yōu)缺點
優(yōu)點:
- 在內(nèi)存中某個類只有一個實例,減少了內(nèi)存的開銷,尤其是頻繁的創(chuàng)建和銷毀實例
- 避免對資源的多重暫用
缺點: 沒有接口,不能繼承
單例模式的幾種實現(xiàn)方式
1、餓漢式(線程安全)
類加載時就初始化實例,避免了多線程同步問題,天然線程安全。
為什么餓漢式是線程安全的? 類加載的方式是按需加載,且只加載一次。因此,在上述單例類被加載時,就會實例化一個對象并交給自己的引用,供系統(tǒng)使用,即在線程訪問單例對象之前,其就已經(jīng)創(chuàng)建好了。線程每次都只能拿到這個唯一的對象。因此,餓漢式單例天生就是線程安全的。
class Singleton{ //1、私有化構(gòu)造器,這樣外部就不能通過構(gòu)造器來創(chuàng)建對象 private Singleton(){ } //2、本類內(nèi)部創(chuàng)建對象實例 private final static Singleton instance = new Singleton(); //3、對外提供一個共有的靜態(tài)方法,返回對象實例 public static Singleton getInstance(){ return instance; } }
2、餓漢式(靜態(tài)代碼塊方式)
class Singleton{ //1、私有化構(gòu)造器,這樣外部就不能通過構(gòu)造器來創(chuàng)建對象 private Singleton(){ } //2、本類內(nèi)部創(chuàng)建對象實例 private static Singleton instance; //3、在靜態(tài)代碼塊中創(chuàng)建單例對象 static { instance = new Singleton(); } //4、對外提供一個共有的靜態(tài)方法,返回對象實例 public static Singleton getInstance(){ return instance; } }
3、懶漢式(線程不安全)
實例對象在第一次被調(diào)用的時候才真正構(gòu)建的,而不是程序一啟動就會自動構(gòu)建。這種實現(xiàn)最大的問題就是不支持多線程,因為沒有加鎖 ,多線程場景下不要使用,因為可能會產(chǎn)生多個對象,不再是單例
class Singleton{ private static Singleton instance; private Singleton(){}; //提供一個靜態(tài)的公有方法,當使用到該方法時,才會去創(chuàng)建instance public static Singleton getInstance(){ if(instance==null){ instance = new Singleton(); } return instance; } }
4、懶漢式+鎖 實現(xiàn)多線程安全的單例模式
每次獲取實例時,也需要等待其他線程的鎖釋放,效率低
class Singleton{ private static Singleton instance; private Singleton(){}; //提供一個靜態(tài)的公有方法,當使用到該方法時,才會去創(chuàng)建instance public static synchronized Singleton getInstance(){ if(instance==null){ instance = new Singleton(); } return instance; } }
5、double-check locking實現(xiàn)單例模式
多個線程只在創(chuàng)建實例的時候加鎖實現(xiàn)同步
class Singleton{ // volatile: 輕量級的synchronized, 由它修飾的變量在發(fā)生變化后會立即刷新到主存 private static volatile Singleton instance; private Singleton(){}; public static Singleton getInstance(){ if(instance==null){ synchronized (Singleton.class){ if(instance==null){ instance = new Singleton(); } } } return instance; } }
【注意】instance為什么需要采? volatile 關鍵字修飾?
instance采? volatile 關鍵字修飾也是很有必要的,在上述代碼中有下面這一句代碼
instance= SingletonDCL();
其實是分為三步執(zhí)?的:
1.為 instance 分配內(nèi)存空間
2. 初始化 instance
3. 將 instance指向分配的內(nèi)存地址
但是由于 JVM 具有指令重排的特性,執(zhí)?順序有可能變成 1->3->2。指令重排在單線程環(huán)境下不會出現(xiàn)問題,但是在多線程環(huán)境下會導致?個線程獲得還沒有初始化的實例。
例如,線程A 執(zhí)?了 1 和3,此時線程B調(diào)? getInstance() 后發(fā)現(xiàn) instance不為空,因此返回instance,但此時instance還未被初始化,使? volatile 可以禁? JVM 的指令重排 ,保證在多線程環(huán)境下也能正常運?。
到此這篇關于Java設計模式之單例模式簡單解析的文章就介紹到這了,更多相關Java的單例模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot2.x只需兩步快速整合log4j2的方法
這篇文章主要介紹了springboot2.x只需兩步快速整合log4j2的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-05-05SpringBoot3整合SpringCloud啟動后nacos報錯獲取不到配置、無法注冊服務的解決方案
文章介紹了如何使用Spring Boot 3.3.4和Spring Cloud 2023.0.3搭建微服務項目,并解決與Nacos服務注冊發(fā)現(xiàn)和配置中心的集成問題,主要解決了依賴版本不兼容、配置文件導入問題及服務注冊失敗等問題,感興趣的朋友跟隨小編一起看看吧2025-02-02Java網(wǎng)絡編程UDP實現(xiàn)消息發(fā)送及聊天
這篇文章主要為大家詳細介紹了Java網(wǎng)絡編程UDP實現(xiàn)消息發(fā)送及聊天,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07flowable動態(tài)創(chuàng)建多級流程模板實現(xiàn)demo
這篇文章主要為大家介紹了flowable動態(tài)創(chuàng)建多級流程模板實現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05JProfiler11使用教程之JVM調(diào)優(yōu)問題小結(jié)
這篇文章主要介紹了JProfiler11使用教程之JVM調(diào)優(yōu),本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03