国产一区二区美女诱惑_国产精品免费播放_91精品国产综合久久香蕉麻豆 _久久精品30_久久综合88_国产精品亚洲成人_黑人极品videos精品欧美裸_亚洲色图欧美激情

原創生活

國內 商業 滾動

基金 金融 股票

期貨金融

科技 行業 房產

銀行 公司 消費

生活滾動

保險 海外 觀察

財經 生活 期貨

當前位置:原創 >

設計模式篇之一文搞懂如何實現單例模式-世界速遞

文章來源:騰訊云  發布時間: 2023-03-20 05:08:00  責任編輯:cfenews.com
+|-

設計模式篇之一文搞懂如何實現單例模式

大家好,我是小簡,這一篇文章,6種單例方法一網打盡,雖然單例模式很簡單,但是也是設計模式入門基礎,我也來詳細講講。

DEMO倉庫:https://github.com/JanYork/DesignPattern ,歡迎PR,共建。


(資料圖片)

單例模式

單例模式(SingletonPattern)是 Java中最簡單的設計模式之一。

單例模式一共存在 --> 懶漢式、餓漢式、懶漢+同步鎖、雙重校驗鎖、靜態內部類、枚舉這六種方式。

這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。

這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。

這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。

要求

單例類只能有一個實例。單例類必須自己創建自己的唯一實例。單例類必須給所有其他對象提供這一實例。

為什么需要使用單例模式

只允許創建一個對象,因此節省內存,加快對象訪問速度,因此對象需要被公用的場合適合使用,如多個模塊使用同一個數據源連接對象等等。解決一個全局使用的類頻繁地創建與銷毀問題。其他場景自行腦部,單例即全局唯一對象,比如我們所熟悉的SpringBean默認就是單例的,全局唯一。

單例原理

單例的原理非常簡單,我們讓他唯一的方法就是讓他不可用被new,那我們只需要私有化類的構造即可:

private ClassName() {}

但是私有化后,我們不能new又如何創建對象呢?

我們首先要明白,private他是私有的,也就是不讓外部其他類訪問,那我們自己還是可以訪問的,所以在上文的要求中就說到了:單例類必須自己創建自己的唯一實例。

同時我們還需要拋出單例的獲取方法。

單例模式之懶漢式

創建單例類

public class SlackerStyle {}

創建一個屬性保存自身對象

public class SlackerStyle {    private static SlackerStyle instance;}

私有化構造

public class SlackerStyle {    private static SlackerStyle instance;    /**     * 私有化構造方法(防止外部new新的對象)     */    private SlackerStyle() {    }}

自身創建對象與獲取對象方法

public class SlackerStyle {    private static SlackerStyle instance;    /**     * 私有化構造方法(防止外部new新的對象)     */    private SlackerStyle() {    }    /**     * 提供一個靜態的公有方法,當使用到該方法時,才去創建instance     * 即懶漢式     *     * @return instance(單例對象)     */    public static SlackerStyle getInstance() {        if (instance == null) {            instance = new SlackerStyle();        }        return instance;    }}

當我們調用靜態方法,它便會判斷上面的靜態屬性instance中有無自身對象,無 --> 創建對象并賦值給instance,有 --> 返回instance

優缺分析

優點:延遲加載,效率較高。缺點:線程不安全,可能會造成多個實例。

解釋:延遲加載 --> 懶漢式只有在需要時才會創建單例對象,可以節約資源并提高程序的啟動速度。

單例模式之懶漢式+鎖

在以上的類中,對getInstance()方法添加synchronized鎖,即可彌補線程不安全缺陷。

/**     * 注意,此段為補充,為了解決線程不安全的問題,可以在方法上加上synchronized關鍵字,但是這樣會導致效率下降     * 提供一個靜態的公有方法,加入同步處理的代碼,解決線程安全問題     * 此方法為線程安全的懶漢式,即懶漢+同步鎖,就不額外寫一個類了     *     * @return instance(單例對象)     */    public static synchronized SlackerStyle getInstance2() {        if (instance == null) {            instance = new SlackerStyle();        }        return instance;    }

雖然彌補了線程不安全的缺陷,但是也失去了一部分效率,所以需要根據業務環境去選擇適合的方法,魚和熊掌不可兼得。

單例模式之餓漢式

還是如開始一樣,創建好單例類,私有化構造方法。

public class HungryManStyle {    /**     * 私有化構造方法(防止外部new新的對象)     */    private HungryManStyle() {    }}

靜態初始化對象

我們餓漢式是延遲加載的,即要用,然后第一次去調用時才會創建對象,而餓漢式恰恰相反,他在初始化類的時候就去創建。

靜態初始化?

我們的static關鍵詞修飾的方法或屬性,在類加載之初遍開辟內存創建好了相關的內容了。

包括每個類的:

static{}

中也一樣的。

所以我們直接使用static修飾。

public class HungryManStyle {    /**     * 靜態變量(單例對象),類加載時就初始化對象(不存在線程安全問題)     */    private static final HungryManStyle INSTANCE = new HungryManStyle();    /**     * 私有化構造方法(防止外部new新的對象)     */    private HungryManStyle() {    }    /**     * 提供一個靜態的公有方法,直接返回INSTANCE     *     * @return instance(單例對象)     */    public static HungryManStyle getInstance() {        return INSTANCE;    }}

而且我們在類的靜態屬性創建時就new了一個自身對象了。

優缺分析

餓漢式的優點如下:

線程安全:由于在類加載時就創建單例對象,因此不存在多線程環境下的同步問題。沒有加鎖的性能問題:餓漢式沒有使用同步鎖,因此不存在加鎖帶來的性能問題。實現簡單:餓漢式的實現比較簡單,不需要考慮多線程環境下的同步問題。

餓漢式的缺點如下:

立即加載:由于在類加載時就創建單例對象,因此可能會影響程序的啟動速度。浪費資源:如果單例對象很大,并且程序中很少使用,那么餓漢式可能會浪費資源。

綜上所述,餓漢式的優點是線程安全、沒有加鎖的性能問題和實現簡單,缺點是可能影響程序的啟動速度和浪費資源。

在選擇單例模式的實現方式時,需要根據實際情況綜合考慮各種因素,選擇最適合的方式。

單例模式之雙重檢查鎖

初始化基本單例類

老規矩。

public class DoubleLockStyle {    /**     * volatile關鍵字,使得instance變量在多個線程間可見,禁止指令重排序優化     * volatile是一個輕量級的同步機制,即輕量鎖     */    private static volatile DoubleLockStyle instance;    /**     * 私有化構造方法(防止外部new新的對象)     */    private DoubleLockStyle() {    }}

不一樣的是,我在屬性上使用volatile關鍵詞修飾了。

volatile?

補充知識啦!

在這個代碼中,使用了 volatile 關鍵字來確保 instance 變量的可見性,避免出現空指針異常等問題。

volatile是一種修飾符,用于修飾變量。當一個變量被聲明為volatile時,線程在訪問該變量時會強制從主內存中讀取變量的值,而不是從線程的本地緩存中讀取。使用volatile關鍵字可以保證多線程之間的變量訪問具有可見性和有序性。在對該變量進行修改時,線程也會將修改后的值強制刷回主內存,而不是僅僅更新線程的本地緩存。

補充:

volatile的主要作用是保證共享變量的可見性和有序性。共享變量是指在多個線程之間共享的變量,例如單例模式中的 instance變量。如果不使用volatile關鍵字修飾 instance變量,在多線程環境下可能會出現空指針異常等問題。

這是因為當一個線程修改了 instance變量的值時,其他線程可能無法立即看到修改后的值,從而出現空指針異常等問題。

使用 volatile關鍵字可以解決這個問題,因為它可以保證對共享變量的修改對其他線程是可見的。

除了可見性和有序性之外,volatile 還可以防止指令重排序。指令重排序是指 CPU 為了提高程序執行的效率而對指令執行的順序進行調整的行為。在單例模式中,如果 instance 變量沒有被聲明為 volatile,那么在多線程環境下可能會出現單例對象被重復創建的問題。這是因為在多線程環境下,某些線程可能會在 instance 變量被初始化之前就調用 getInstance()方法,從而導致多次創建單例對象。通過將 instance 變量聲明為 volatile,可以保證在創建單例對象之前,instance 變量已經被正確地初始化了。

雙重鎖

/** * 提供一個靜態的公有方法,加入雙重檢查代碼,解決線程安全問題,同時解決懶加載問題 * 即雙重檢查鎖模式 * * @return instance(單例對象) */public static DoubleLockStyle getInstance() {    if (instance == null) {        // 同步代碼塊,線程安全的創建實例        synchronized (DoubleLockStyle.class) {            //之所以要再次判斷,是因為可能有多個線程同時進入了第一個if判斷            if (instance == null) {                instance = new DoubleLockStyle();            }        }    }    return instance;}

在獲取方法中,使用synchronized來同步,使它線程安全。

有缺分析

雙重鎖模式是一種用于延遲初始化的優化模式,在第一次調用時創建單例對象,并在之后的訪問中直接返回該對象。它通過使用雙重檢查鎖定(double checked locking)來保證在多線程環境下只有一個線程可以創建單例對象,并且不會加鎖影響程序性能。

優點:

線程安全:使用雙重鎖模式可以保證在多線程環境下只有一個線程可以創建單例對象,并且不會加鎖影響程序性能。延遲初始化:在第一次調用時創建單例對象,可以避免不必要的資源浪費和內存占用。性能優化:通過使用雙重檢查鎖定,可以避免不必要的鎖競爭,從而提高程序性能。

缺點:

實現復雜:雙重鎖模式的實現相對復雜,需要考慮線程安全和性能等因素,容易出現錯誤。可讀性差:由于雙重鎖模式的實現比較復雜,代碼可讀性較差,不易于理解和維護。難以調試:由于雙重鎖模式涉及到多線程并發訪問,因此在調試過程中可能會出現一些難以定位和復現的問題。

一個synchronized為何叫雙重鎖?

在雙重鎖模式中,確實只有一個 synchronized關鍵字,但是這個 synchronized關鍵字是在代碼中被使用了兩次,因此被稱為“雙重鎖”。

具體來說,雙重鎖模式通常會在 getInstance方法中使用 synchronized關鍵字來保證線程安全,但是這會影響程序的性能,因為每次訪問 getInstance方法都需要獲取鎖。為了避免這個問題,雙重鎖模式使用了一個優化技巧,即只有在第一次調用 getInstance方法時才會獲取鎖并創建單例對象,以后的調用都直接返回已經創建好的單例對象,不需要再獲取鎖。

具體實現時,雙重鎖模式會在第一次調用 getInstance方法時進行兩次檢查,分別使用外部的 if語句和內部的 synchronized關鍵字。外部的 if語句用于判斷單例對象是否已經被創建,如果已經被創建則直接返回單例對象,否則進入內部的 synchronized關鍵字塊,再次檢查單例對象是否已經被創建,如果沒有被創建則創建單例對象并返回,否則直接返回已經創建好的單例對象。

這樣做的好處是,在多線程環境下,只有一個線程可以進入內部的 synchronized關鍵字塊,從而保證了線程安全,同時避免了每次訪問 getInstance方法都需要獲取鎖的性能問題。

單例模式之靜態內部類

因為已經熟悉了這個設計模式原理,我就直接放代碼了。

public class StaticInnerClassStyle {    /**     * 私有化構造方法(防止外部new新的對象)     */    private StaticInnerClassStyle() {    }    /**     * 靜態內部類     */    private static class SingletonInstance {        // 靜態內部類中的靜態變量(單例對象)        private static final StaticInnerClassStyle INSTANCE = new StaticInnerClassStyle();    }    /**     * 提供一個靜態的公有方法,直接返回SingletonInstance.INSTANCE     *     * @return instance(單例對象)     */    public static StaticInnerClassStyle getInstance() {        return SingletonInstance.INSTANCE;    }}

優缺分析

優點:

線程安全:靜態內部類在第一次使用時才會被加載,因此在多線程環境下也可以保證只有一個線程創建單例對象,避免了線程安全問題。延遲加載:靜態內部類模式可以實現延遲加載,即只有在第一次調用 getInstance方法時才會加載內部類并創建單例對象,避免了在程序啟動時就創建單例對象的開銷。

缺點:

需要額外的類:靜態內部類模式需要定義一個額外的類來實現單例模式,如果項目中有大量的單例對象,則會增加代碼量。無法傳遞參數:靜態內部類模式無法接受參數,因此無法在創建單例對象時傳遞參數,這可能會對某些場景造成限制。

總的來說,靜態內部類模式是一種性能高、線程安全的單例模式實現方式,適用于大部分場景。

如果需要傳遞參數或者需要頻繁創建單例對象,則可能需要考慮其他的實現方式。

它不是static修飾嗎?為什么也可以懶加載

懶加載即延時加載 --> 使用時采取創建對象。

在靜態內部類模式中,單例對象是在靜態內部類中被創建的。靜態內部類只有在第一次被使用時才會被加載,因此單例對象也是在第一次使用時被創建的。這樣就實現了延遲加載的效果,即在需要時才創建單例對象,避免了在程序啟動時就創建單例對象的開銷。

此外,靜態內部類中的靜態變量和靜態方法是在類加載時被初始化的,而靜態內部類本身是非常輕量級的,加載和初始化的時間和開銷都非常小。因此,靜態內部類模式既能夠實現懶加載,又不會帶來太大的性能損失。

總之,它在靜態初始化意料之外,我相信也在你意料之外。

單例模式之枚舉單例

/** * @author JanYork * @date 2023/3/1 17:54 * @description 設計模式之單例模式(枚舉單例) * 優點:避免序列化和反序列化攻擊破壞單例,避免反射攻擊破壞單例(枚舉類型構造函數是私有的),線程安全,延遲加載,效率較高。 * 缺點:代碼復雜度較高。 */public enum EnumerateSingletons {    /**     * 枚舉單例     */    INSTANCE;    public void whateverMethod() {        // TODO:do something ,在這里實現單例對象的功能    }}

在上述代碼中,INSTANCEEnumSingleton類型的一個枚舉常量,表示單例對象的一個實例。由于枚舉類型的特性,INSTANCE會被自動初始化為單例對象的一個實例,并且保證在整個應用程序的生命周期中只有一個實例。

使用枚舉單例的方式非常簡單,只需要通過 EnumSingleton.INSTANCE的方式來獲取單例對象即可。例如:

EnumerateSingletons singleton = EnumerateSingletons.INSTANCE;singleton.doSomething();

使用枚舉單例的好處在于,它是線程安全、序列化安全、反射安全的,而且代碼簡潔明了,不容易出錯。另外,枚舉單例還可以通過枚舉類型的特性來添加其他方法和屬性,非常靈活。

優缺分析

線程安全:枚舉類型的實例創建是在類加載的時候完成的,因此不會出現多個線程同時訪問創建單例實例的問題,保證了線程安全。序列化安全:枚舉類型默認實現了序列化,因此可以保證序列化和反序列化過程中單例的一致性。反射安全:由于枚舉類型的特殊性,不會被反射機制創建多個實例,因此可以保證反射安全。簡潔明了:枚舉單例的代碼非常簡潔,易于理解和維護。

枚舉單例的缺點相對來說比較少,但是也存在一些限制:

不支持懶加載:枚舉類型的實例創建是在類加載的時候完成的,因此無法實現懶加載的效果。無法繼承:枚舉類型不能被繼承,因此無法通過繼承來擴展單例類的功能。有些情況下不太方便使用:例如需要傳遞參數來創建單例對象的場景,使用枚舉單例可能不太方便。

總之,枚舉單例是一種非常優秀的單例實現方式,它具有線程安全、序列化安全、反射安全等優點,適用于大多數單例場景,但也存在一些限制和局限性。需要根據具體的場景來選擇合適的單例實現方式。

這么多方式我該怎么選?

設計模式本就是業務中優化一些設計帶來的概念性設計,我們需要結合業務分析:

餓漢式:適用于單例對象較小、創建成本低、不需要懶加載的場景。懶漢式:雙重鎖:適用于多線程環境,對性能要求較高的場景。靜態內部類:適用于多線程環境,對性能要求較高的場景。枚舉:適用于單例對象創建成本較高,且需要考慮線程安全、序列化安全、反射安全等問題的場景。

如果你的單例對象創建成本低、不需要考慮線程安全、序列化安全、反射安全等問題,建議使用餓漢式實現單例;如果需要考慮線程安全和性能問題,可以選擇懶漢式的雙重鎖或靜態內部類實現方式;如果需要考慮單例對象創建成本較高,需要考慮線程安全、序列化安全、反射安全等問題,建議選擇枚舉單例實現方式。當然,在實際的開發中,還需要考慮其他一些因素,如單例對象的生命周期、多線程訪問情況、性能要求、并發訪問壓力等等,才能綜合選擇最合適的單例實現方式。

Java程序員身邊的單例模式

來自某AI(敏感詞):

關鍵詞:

專題首頁|財金網首頁

投資
探索

精彩
互動

獨家
觀察

京ICP備2021034106號-38   營業執照公示信息  聯系我們:55 16 53 8 @qq.com  財金網  版權所有  cfenews.com
亚洲精品国产精品国产自| 日本网站在线观看一区二区三区| 99久久99视频只有精品| 欧美二区视频| 蜜芽一区二区三区| 久久新电视剧免费观看| 亚洲在线免费播放| 欧美日韩一本到| 亚洲国产精品久久久| 亚洲成人影院在线观看| caoprom在线| 国产精品对白久久久久粗| 一区二区三区午夜视频| 久草热8精品视频在线观看| 久久精品日产第一区二区三区高清版| 一区二区三区免费在线观看| 欧美性大战xxxxx久久久| 成人丁香基地| 超碰免费公开在线| 亚洲精品一区二区在线播放∴| 成人精品电影| 九一九一国产精品| 欧美高清在线一区| 欧美一区二区网站| 国产午夜视频在线观看| 日韩免费在线电影| 欧美日本亚洲韩国国产| 国产拍在线视频| 亚洲婷婷综合久久一本伊一区| 91高清视频在线| 天天爽夜夜爽夜夜爽精品视频| 亚洲天堂网中文字| 青青草精品视频| 爱高潮www亚洲精品| 神马精品久久| 亚洲激情视频网| 黄色网页在线免费观看| 视频在线不卡| 韩国女主播一区二区三区| 奇米888四色在线精品| 久久久综合精品| 日韩精品在线看片z| 日韩av在线资源| gogo在线观看| 欧美aaa免费| 国产乱人伦精品一区| 一本久久综合| 国产精品天美传媒| 男人的天堂久久精品| 日韩精品视频网站| 亚洲专区欧美专区| 欧美日免费三级在线| 亚洲人成在线观看| 日本中文在线| 国产精品久久免费视频| av手机在线观看| 欧美一区视频| 国产精品国产精品国产专区不片| 日韩精品久久久久久福利| 欧美电影免费观看高清完整| 亚洲特色特黄| 欧美日韩一二三区| 欧美黄色a视频| 天堂成人娱乐在线视频免费播放网站 | 欧美日韩中文字幕综合视频 | 成人午夜电影小说| 在线日韩一区二区| 国产精品va在线观看视色| 精品免费在线| 中文字幕欧美一区| 污视频在线观看免费| 美女网站一区| 国产精品盗摄一区二区三区| 992tv在线观看免费进| 久久九九热re6这里有精品| 97国产一区二区| 国产午夜视频| 五月综合久久| 亚洲色图20p| 免费在线黄色影片| 欧美成人国产| 一本色道久久综合亚洲aⅴ蜜桃| 日本在线免费| 久久国产精品久久w女人spa| 欧美日韩一区二区不卡| 成人美女黄网站| 蜜臀av性久久久久av蜜臀妖精| 日韩限制级电影在线观看| 国产麻豆久久| 99久久精品免费看| 麻豆免费网站| 日本午夜一区| 欧美日韩中文字幕| 日本在线中文字幕一区二区三区| 国产精品88av| 超碰97在线免费| 国产欧美一区| 一本久道久久综合中文字幕 | 成人免费av网站| 中文字幕在线免费专区| 一本到12不卡视频在线dvd| 色视频一区二区| 欧美黑人疯狂性受xxxxx野外| 国产999精品久久久久久绿帽| 天天干夜夜干| 欧美久久影院| 精品国产凹凸成av人网站| 农村少妇一区二区三区四区五区| 亚洲精品一二三区| 欧美少妇网站| 91在线国产福利| 91caoporm在线视频| 久久久成人网| av手机在线看| 91影院成人| 337p亚洲精品色噜噜噜| 九九热hot精品视频在线播放| 亚洲综合精品自拍| 色999久久久精品人人澡69 | 老司机在线永久免费观看| 免费欧美在线视频| 四虎精品成人影院观看地址| 国产欧美日韩综合一区在线播放 | 欧美v国产在线一区二区三区| 日韩a级大片| 在线免费观看一区| 国产精品chinese在线观看| 亚洲国产日韩精品| 国语精品视频| 色综合色综合色综合 | 伊人精品久久| 欧美日韩国产一中文字不卡| 精品视频在线播放一区二区三区 | 精品久久久久久久久中文字幕| 日日夜夜亚洲| 欧美日韩一区免费| 66精品视频在线观看| 欧美视频在线播放| 91亚洲人成网污www| 亚洲精品小视频在线观看| 99日韩精品| 亚洲精品男人| 成人高清在线视频| 人成在线免费网站| 亚洲国产精品尤物yw在线观看| 亚洲精品影片| 日韩一区二区影院| 精品白丝av| 国产一区电影| 久久精品一区四区| 国产精品亚洲欧美日韩一区在线 | 欧美日韩mp4| 午夜久久一区| 在线看小视频| 久久奇米777| 成人亚洲免费| 欧美日韩大陆在线| 欧美午夜电影在线观看| 亚洲日本高清| 久久久久久久一区| 四虎永久精品在线| 欧美一区二区三区白人| 亚洲一区日韩在线| 成人在线播放免费观看| 亚洲欧美国产三级| 国产亚洲电影| 黄污在线观看| 久久久99久久| 另类图片第一页| 亚洲欧洲自拍偷拍| 国产美女精品在线| 亚洲成人短视频| 91精品国产综合久久精品性色 | 日韩一级二级三级精品视频| 日韩综合小视频| 欧美aaaxxxx做受视频| 日本韩国视频一区二区| 在线日本成人| 污视频免费在线观看| 色综合天天综合网天天看片| 中出一区二区| 亚洲s色大片| 精品久久久久久久久中文字幕 | 日本不卡1区2区3区| 白白色 亚洲乱淫| 都市激情亚洲| 欧美最顶级a∨艳星| 亚洲欧美日韩系列| 久久久久久久久久久9不雅视频 | 亚洲成人高清在线| 亚洲经典自拍| 欧美freesex黑人又粗又大| 欧美一区二区在线不卡| 国产精品一区二区三区99| 中文成人在线| 国产一级粉嫩xxxx| 国产精品天美传媒| 9191国语精品高清在线| 在线三级电影| 日韩三级视频中文字幕|