Java單例模式的幾種常見寫法
1.餓漢模式
餓漢模式也叫預(yù)加載模式,它是在類加載時(shí)直接創(chuàng)建并初始化單例對(duì)象,所以它并不存在線程安全的問題。它是依靠 ClassLoader 類機(jī)制,在程序啟動(dòng)時(shí)只加載一次,因此不存在線程安全問題,它的實(shí)現(xiàn)代碼如下:
public class Singleton { // 1.防止外部直接 new 對(duì)象破壞單例模式 private Singleton() {} // 2.通過私有變量保存單例對(duì)象 private static Singleton instance = new Singleton(); // 3.提供公共獲取單例對(duì)象的方法 public static Singleton getInstance() { return instance; } }
優(yōu)點(diǎn):實(shí)現(xiàn)簡單、不存在線程安全問題。 缺點(diǎn):類加載時(shí)就創(chuàng)建了對(duì)象,創(chuàng)建之后如果沒被使用,就造成了資源浪費(fèi)的情況。
2.懶漢模式
懶漢模式和餓漢模式正好是相反的,所謂的懶漢模式也就是懶加載(延遲加載),指的是它只有在第一次被使用時(shí),才會(huì)被初始化,
它的實(shí)現(xiàn)代碼如下:
public class Singleton { // 1.防止外部直接 new 對(duì)象破壞單例模式 private Singleton() {} // 2.通過私有變量保存單例對(duì)象 private static volatile Singleton instance = null; // 3.提供公共獲取單例對(duì)象的方法 public static Singleton getInstance() { if (instance == null) { // 第一次效驗(yàn) synchronized (Singleton.class) { if (instance == null) { // 第二次效驗(yàn) instance = new Singleton(); } } } return instance; } }
懶漢模式使用的是雙重效驗(yàn)鎖和 volatile 來保證線程安全的,從上述代碼可以看出,無論是餓漢模式還是懶漢模式,它們的實(shí)現(xiàn)步驟都是一樣的:
- 創(chuàng)建一個(gè)私有的構(gòu)造方法,防止其他調(diào)用的地方直接 new 對(duì)象,這樣創(chuàng)建出來的對(duì)象就不是單例對(duì)象了。
- 創(chuàng)建一個(gè)私有變量來保存單例對(duì)象。
- 提供一個(gè)公共的方法返回單例對(duì)象。
懶漢模式相比于餓漢模式來說,不會(huì)造成資源的浪費(fèi),但寫法要復(fù)雜一些。
3.靜態(tài)內(nèi)部類
靜態(tài)內(nèi)部類既能保證線程安全,又能保證懶加載,它只有在被調(diào)用時(shí),才會(huì)通過 ClassLoader 機(jī)制來加載和初始化內(nèi)部靜態(tài)類,因此它是線程安全的,此模式的實(shí)現(xiàn)代碼如下:
public class Singleton { // 1.防止外部直接 new 對(duì)象破壞單例模式 private Singleton() { } // 2.靜態(tài)內(nèi)部類 private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } // 3.提供公共獲取單例對(duì)象的方法 public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
4.枚舉
枚舉也是在第一次被使用時(shí),才會(huì)被 Java 虛擬機(jī)加載并初始化,所以它也是線程安全的,且是懶加載的,它的實(shí)現(xiàn)代碼如下:
public enum EnumSingleton { INSTANCE; public EnumSingleton getInstance(){ return INSTANCE; } }
總結(jié)
單例模式適用于經(jīng)常被訪問的對(duì)象,或是創(chuàng)建和銷毀需要調(diào)用大量資源和時(shí)間的對(duì)象,使用單例模式可以避免頻繁創(chuàng)建和銷毀對(duì)象。單例模式的常用實(shí)現(xiàn)方法有 4 種:餓漢模式、懶漢模式、靜態(tài)內(nèi)部類和枚舉。從寫法的簡潔性、線程安全性和代碼的易懂性等方面綜合來看,博主比較推薦使用枚舉或懶漢模式來實(shí)現(xiàn)單例模式。
到此這篇關(guān)于Java單例模式的幾種寫法的文章就介紹到這了,更多相關(guān)Java單例模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Web項(xiàng)目中驗(yàn)證碼功能的制作攻略
使用servlet制作驗(yàn)證碼中最關(guān)鍵的部分是緩存的使用,驗(yàn)證session中的字符串,接下來我們就來看一下Java Web項(xiàng)目中驗(yàn)證碼功能的制作攻略2016-05-05Spring實(shí)現(xiàn)動(dòng)態(tài)修改時(shí)間參數(shù)并手動(dòng)開啟關(guān)停操作
spring實(shí)現(xiàn)定時(shí)任務(wù)的方式有三種,分別是java自帶的timer類、spring task和quartz三種。本文只介紹spring自帶的task和第三方quartz,感興趣的朋友參考下吧2017-09-09java 實(shí)現(xiàn)通過 post 方式提交json參數(shù)操作
這篇文章主要介紹了java 實(shí)現(xiàn)通過 post 方式提交json參數(shù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09Java對(duì)世界不同時(shí)區(qū)timezone之間時(shí)間轉(zhuǎn)換的處理方法
這篇文章主要介紹了Java對(duì)世界不同時(shí)區(qū)timezone之間時(shí)間轉(zhuǎn)換的處理方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07SpringCloud?Gateway詳細(xì)分析實(shí)現(xiàn)負(fù)載均衡與熔斷和限流
這篇文章主要介紹了SpringCloud?Gateway實(shí)現(xiàn)路由轉(zhuǎn)發(fā),負(fù)載均衡,熔斷和限流,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07spring-cloud入門之spring-cloud-config(配置中心)
這篇文章主要介紹了spring-cloud入門之spring-cloud-config(配置中心),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01關(guān)于scanner.nextInt()等next()和scanner.nextIine()連用注意事項(xiàng)
這篇文章主要介紹了關(guān)于scanner.nextInt()等next()和scanner.nextIine()連用注意事項(xiàng),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2023-04-04java實(shí)現(xiàn)圖片轉(zhuǎn)ascii字符畫的方法示例
這篇文章主要介紹了java實(shí)現(xiàn)圖片轉(zhuǎn)ascii字符畫的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08如何在Spring Boot應(yīng)用中優(yōu)雅的使用Date和LocalDateTime的教程詳解
這篇文章主要介紹了如何在Spring Boot應(yīng)用中優(yōu)雅的使用Date和LocalDateTime,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07Java線程中斷機(jī)制interrupt、isInterrupted、interrupted方法詳解
這篇文章主要介紹了Java線程中斷機(jī)制interrupt、isInterrupted、interrupted方法詳解,一個(gè)線程不應(yīng)該由其他線程來強(qiáng)制中斷或停止,而是應(yīng)該由線程自己自行停止,所以,Thread.stop、Thread.suspend、Thread. resume都已經(jīng)被廢棄了,需要的朋友可以參考下2024-01-01