国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

單例模式你會幾種寫法?

solocoder / 2146人閱讀

摘要:使用靜態(tài)類體現(xiàn)的是基于對象,而使用單例設(shè)計(jì)模式體現(xiàn)的是面向?qū)ο蟆6帉憜卫J降拇a編寫單例模式的代碼其實(shí)很簡單,就分了三步將構(gòu)造函數(shù)私有化在類的內(nèi)部創(chuàng)建實(shí)例提供獲取唯一實(shí)例的方法餓漢式根據(jù)上面的步驟,我們就可以輕松完成創(chuàng)建單例對象了。

前言
只有光頭才能變強(qiáng)

回顧前面:

給女朋友講解什么是代理模式

包裝模式就是這么簡單啦

本來打算沒那么快更新的,這陣子在刷Spring的書籍。在看Spring的時(shí)候又經(jīng)常會看到“單例”,“工廠”這些字樣。

所以,就先來說說單例和工廠設(shè)計(jì)模式啦,這兩種模式也是很常見的,我看很多面經(jīng)都會遇到這兩種模式~

本文主要講解單例設(shè)計(jì)模式,如果有錯(cuò)的地方希望能多多包涵,并不吝在評論區(qū)指正!

一、單例模式概述

單例模式定義很簡單:一個(gè)類中能創(chuàng)建一個(gè)實(shí)例,所以稱之為單例!

那我們什么時(shí)候會用到單例模式呢??

那我們想想既然一個(gè)類中只能創(chuàng)建一個(gè)實(shí)例了,那么可以說這是跟類的狀態(tài)與對象無關(guān)的了。

頻繁創(chuàng)建對象、管理對象是一件耗費(fèi)資源的事,我們只需要創(chuàng)建一個(gè)對象來用就足夠了!

學(xué)過Java Web的同學(xué)可能就知道:

Servlet是單例的

Struts2是多例的

SpringMVC是單例的

那既然多例是頻繁創(chuàng)建對象、需要管理對象的,那Struts2為什么要多例呢??

主要由于設(shè)計(jì)層面上的問題,Struts2是基于Filter攔截類的,ognl引擎對變量是注入的。所以它要設(shè)計(jì)成多例的~

能使用一個(gè)對象來做就不用實(shí)例化多個(gè)對象!這就能減少我們空間和內(nèi)存的開銷~

那有可能有的人又會想了:我們使用靜態(tài)類.doSomething()和使用單例對象調(diào)用方法的效果是一樣的啊。

沒錯(cuò),效果就是一樣的。使用靜態(tài)類.doSomething()體現(xiàn)的是基于對象,而使用單例設(shè)計(jì)模式體現(xiàn)的是面向?qū)ο?/strong>。

二、編寫單例模式的代碼

編寫單例模式的代碼其實(shí)很簡單,就分了三步:

將構(gòu)造函數(shù)私有化

在類的內(nèi)部創(chuàng)建實(shí)例

提供獲取唯一實(shí)例的方法

2.1餓漢式

根據(jù)上面的步驟,我們就可以輕松完成創(chuàng)建單例對象了。

public class Java3y {

    // 1.將構(gòu)造函數(shù)私有化,不可以通過new的方式來創(chuàng)建對象
    private Java3y(){}

    // 2.在類的內(nèi)部創(chuàng)建自行實(shí)例
    private static Java3y java3y = new Java3y();

    // 3.提供獲取唯一實(shí)例的方法
    public static Student getJava3y() {
        return java3y;
    }
}

這種代碼我們稱之為:“餓漢式”:

一上來就創(chuàng)建對象了,如果該實(shí)例從始至終都沒被使用過,則會造成內(nèi)存浪費(fèi)

2.2簡單懶漢式

既然說一上來就創(chuàng)建對象,如果沒有用過會造成內(nèi)存浪費(fèi):

那么我們就設(shè)計(jì)用到的時(shí)候再創(chuàng)建對象

public class Java3y {

    // 1.將構(gòu)造函數(shù)私有化,不可以通過new的方式來創(chuàng)建對象
    private Java3y(){}

    // 2.1先不創(chuàng)建對象,等用到的時(shí)候再創(chuàng)建
    private static Java3y java3y = null;

    // 2.1調(diào)用到這個(gè)方法了,證明是要被用到的了
    public static Java3y getJava3y() {

        // 3. 如果這個(gè)對象引用為null,我們就創(chuàng)建并返回出去
        if (java3y == null) {
            java3y = new Java3y();
        }

        return java3y;
    }
}

上面的代碼行不行??在單線程環(huán)境下是行的,在多線程環(huán)境下就不行了

如果不知道為啥在多線程環(huán)境下不行的同學(xué)可參考我之前的博文:多線程基礎(chǔ)必要知識點(diǎn)!看了學(xué)習(xí)多線程事半功倍

要解決也很簡單,我們只要加鎖就行了:

2.3雙重檢測機(jī)制(DCL)懶漢式

上面那種直接在方法上加鎖的方式其實(shí)不夠好,因?yàn)樵?strong>方法上加了內(nèi)置鎖在多線程環(huán)境下性能會比較低下,所以我們可以將鎖的范圍縮小

public class Java3y {


    private Java3y() {
    }

    private static Java3y java3y = null;


    public static Java3y getJava3y() {
        if (java3y == null) {
            // 將鎖的范圍縮小,提高性能
            synchronized (Java3y.class) {
                java3y = new Java3y();
            }
        }
        return java3y;
    }
}

那上面的代碼可行嗎??不行,因?yàn)殡m然加了鎖,但還是有可能創(chuàng)建出兩個(gè)對象出來的:

線程A和線程B同時(shí)調(diào)用getJava3y()方法,他們同時(shí)判斷java==null,得出的結(jié)果都是為null,所以進(jìn)入了if代碼塊了

此時(shí)線程A得到CPU的控制權(quán)-->進(jìn)入同步代碼塊-->創(chuàng)建對象-->返回對象

線程A完成了以后,此時(shí)線程B得到了CPU的控制權(quán)。同樣是-->進(jìn)入同步代碼塊-->創(chuàng)建對象-->返回對象

很明顯的是:Java3y類返回了不止一個(gè)實(shí)例!所以上面的代碼是不行的!

有的同學(xué)可能覺得我瞎吹比,明明加鎖了還不行?我們來測試一下:

public class TestDemo {

    public static void main(String[] args) {

        // 線程A
        new Thread(() -> {

            // 創(chuàng)建單例對象
            Java3y java3y = Java3y.getJava3y();
            System.out.println(java3y);

        }).start();

        // 線程B
        new Thread(() -> {
            // 創(chuàng)建單例對象
            Java3y java3y = Java3y.getJava3y();
            System.out.println(java3y);
        }).start();

        // 線程C
        new Thread(() -> {
            // 創(chuàng)建單例對象
            Java3y java3y = Java3y.getJava3y();
            System.out.println(java3y);
        }).start();

    }
}

可以看到,打印出的對象不單單只有一個(gè)的!

厲害的程序員又想到了:進(jìn)入同步代碼塊時(shí)再判斷一下對象是否存在就穩(wěn)了吧

所以,有了下面的代碼

public class Java3y {


    private Java3y() {
    }

    private static Java3y java3y = null;

    public static Java3y getJava3y() {
        if (java3y == null) {

            // 將鎖的范圍縮小,提高性能
            synchronized (Java3y.class) {

                // 再判斷一次是否為null
                if (java3y == null) {
                    java3y = new Java3y();
                }
            }
        }
        return java3y;
    }
}

其實(shí)還不穩(wěn)!這里會有重排序的問題

本來想測試重排序問題的效果的,一直沒測試出來~~~有相關(guān)測試代碼的希望可以告訴我怎么能測出來....

要解決也十分簡單,加上我們的volatile關(guān)鍵字就可以了,volatile有內(nèi)存屏障的功能

具體可參考資料:

https://www.zhihu.com/question/35268028----雙重檢查鎖失效是因?yàn)閷ο蟮某跏蓟⒎窃硬僮鳎?/p>

http://ifeve.com/doublecheckedlocking/---有關(guān)“雙重檢查鎖定失效”的說明

https://my.oschina.net/u/866190/blog/205454----正確使用雙重檢查鎖(DCL)

所以說,完整的DCL代碼是這樣子的:


public class Java3y {
    private Java3y() {
    }

    private static volatile Java3y java3y = null;

    public static Java3y getJava3y() {
        if (java3y == null) {

            // 將鎖的范圍縮小,提高性能
            synchronized (Java3y.class) {

                // 再判斷一次是否為null
                if (java3y == null) {
                    java3y = new Java3y();
                }
            }
        }
        return java3y;
    }
}

再說明:

2.4靜態(tài)內(nèi)部類懶漢式

還可以使用靜態(tài)內(nèi)部類這種巧妙的方式來實(shí)現(xiàn)單例模式!它的原理是這樣的:

當(dāng)任何一個(gè)線程第一次調(diào)用getInstance()時(shí),都會使SingletonHolder被加載和被初始化,此時(shí)靜態(tài)初始化器將執(zhí)行Singleton的初始化操作。(被調(diào)用時(shí)才進(jìn)行初始化!)

初始化靜態(tài)數(shù)據(jù)時(shí),Java提供了的線程安全性保證。(所以不需要任何的同步)

public class Java3y {


    private Java3y() {
    }

    // 使用內(nèi)部類的方式來實(shí)現(xiàn)懶加載
    private static class LazyHolder {
        // 創(chuàng)建單例對象
        private static final Java3y INSTANCE = new Java3y();
    }


    // 獲取對象
    public static final Java3y getInstance() {
        return LazyHolder.INSTANCE;
    }
    
}

靜態(tài)內(nèi)部類這種方式是非常推薦使用的!很多人沒接觸過單例模式的都不知道有這種寫法,這種寫法很優(yōu)化也高效!

參考資料:

https://www.zhihu.com/question/35454510/answer/62829602----java 單例模式通過內(nèi)部靜態(tài)類的方式?

2.5枚舉方式實(shí)現(xiàn)

使用枚舉就非常簡單了:

public enum Java3y3y {
    
    JAVA_3_Y_3_Y,
}

那這種有啥好處??枚舉的方式實(shí)現(xiàn):

簡單,直接寫就行了

防止多次實(shí)例化,即使是在面對復(fù)雜的序列化或者反射攻擊的時(shí)候(安全)!

這種也較為推薦使用!

三、總結(jié)

總的來說單例模式寫法有5種:

餓漢式

簡單懶漢式(在方法加鎖)

DCL雙重檢測加鎖(進(jìn)階懶漢式)

靜態(tài)內(nèi)部類實(shí)現(xiàn)懶漢式(最推薦寫法)

枚舉方式(最安全、簡潔寫法)

明天估計(jì)寫的是工廠模式了,敬請期待哦~~~

參考資料:

《設(shè)計(jì)模式之禪》

http://www.cnblogs.com/seesea125/archive/2012/04/05/2433463.html---為什么要用單例模式?

https://zhuanlan.zhihu.com/p/32310340---圣誕節(jié),讓我們聊聊單例模式

https://zhuanlan.zhihu.com/p/34406410---單例模式詳解

http://www.nowamagic.net/librarys/veda/detail/1776---使用單例模式需要注意的幾個(gè)問題

https://zhuanlan.zhihu.com/p/23713957---Java設(shè)計(jì)模式(一)-單例模式

如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號:Java3y。為了大家方便,剛新建了一下qq群:742919422,大家也可以去交流交流。謝謝支持了!希望能多介紹給其他有需要的朋友

文章的目錄導(dǎo)航

https://zhongfucheng.bitcron.com/post/shou-ji/wen-zhang-dao-hang

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/69406.html

相關(guān)文章

  • 多列轉(zhuǎn)單列表格的三種辦法,你會幾種

    摘要:,各位同學(xué)好我是吳明課堂的答疑老師之一陳婉,我又來了這次我為大家?guī)砹艘粋€(gè)多列轉(zhuǎn)一列的表格案例,效果演示圖如下多列轉(zhuǎn)單列表格的三種辦法,你會幾種在 Hi,各位同學(xué)好!我是吳明課堂的答疑老師之一陳婉,我又來了!這次我為大家?guī)砹艘粋€(gè)多列轉(zhuǎn)一列的表格案例,效果演示圖如下:在這個(gè)案例中,需要把數(shù)據(jù)源中的電話、電視機(jī)、手表、智能手...

    番茄西紅柿 評論0 收藏2637
  • 2017年前端流行的數(shù)百個(gè)javascript庫,會幾個(gè)?

    摘要:有數(shù)百個(gè)免費(fèi)的庫出來,為應(yīng)用程序選擇正確的框架變得非常困難。是流行的驅(qū)動技術(shù)之一,由于年創(chuàng)建。在這三個(gè)塊中,有幾個(gè)暴露低層接口的綁定。反應(yīng)由,和許多開發(fā)人員和個(gè)人的社區(qū)維護(hù)。誕生于年,是一個(gè)輕量級的框架。 有數(shù)百個(gè)免費(fèi)的JS庫出來,為應(yīng)用程序選擇正確的JavaScript框架變得非常困難。一些開發(fā)商最終會拋棄,而其他開發(fā)者則迅速發(fā)展,并得到廣泛采用。許多開發(fā)人員只知道像jQuery和R...

    CoXie 評論0 收藏0
  • Spring IOC知識點(diǎn)一網(wǎng)打盡!

    摘要:使用的好處知乎的回答不用自己組裝,拿來就用。統(tǒng)一配置,便于修改。 前言 只有光頭才能變強(qiáng) 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 單例模式你會幾種寫法? 工廠模式理解了沒有? 在刷Spring書籍的時(shí)候花了點(diǎn)時(shí)間去學(xué)習(xí)了單例模式和工廠模式,總的來說還是非常值得的! 本來想的是刷完《Spring 實(shí)戰(zhàn) (第4版)》和《精通Spring4.x 企業(yè)應(yīng)用開發(fā)實(shí)戰(zhàn)》...

    djfml 評論0 收藏0
  • java單例模式幾種實(shí)現(xiàn)方式分析

    摘要:餓漢模式線程安全,調(diào)用效率高,但是不能延時(shí)加載這樣做的好處是編寫簡單,但是無法做到延遲創(chuàng)建對象。考慮線程安全的寫法這種寫法考慮了線程安全,將對的判斷以及的部分使用進(jìn)行加鎖。如此即可從語義上保證這種單例模式寫法是線程安全的。 餓漢模式 線程安全,調(diào)用效率高,但是不能延時(shí)加載 public class ImageLoader{ private static ImageLoade...

    GT 評論0 收藏0
  • 單例模式幾種寫法

    摘要:單例模式要點(diǎn)私有的構(gòu)造方法指向?qū)嵗乃接徐o態(tài)引用獲取實(shí)例對象的公有靜態(tài)方法餓漢模式非線程安全私有化構(gòu)造函數(shù)懶漢模式非線程安全私有化構(gòu)造函數(shù)雙重線程鎖檢查單例線程安全私有化構(gòu)造函數(shù)枚舉單例更多關(guān)于的文章請戳這里您的留言意見是對我最大的支持我的 單例模式要點(diǎn) 私有的構(gòu)造方法 指向?qū)嵗乃接徐o態(tài)引用 獲取實(shí)例對象的公有靜態(tài)方法 餓漢模式(非線程安全) public class Singl...

    Youngs 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<