1. 程式人生 > >不管你年底換不換工作,瞭解下單例模式

不管你年底換不換工作,瞭解下單例模式

1. 單例模式

什麼是單例模式?簡言之就是確保定義為單例模式的類在程式中有且只有一個例項。單例模式的特點:

  1. 只有一個例項 (只能有一個物件被建立)

  2. 自我例項化(類構造器私有)

  3. 對外提供獲取例項的靜態方法

2.單例模式的實現

常見的單例模式實現方式有五種:

2.1. 懶漢式

懶漢式(一般也稱之為 飽漢式),具體程式碼實現如下:


public class Singleton {

    /**
     * 自我例項化
     */
    private static Singleton singleton;

    /**
     * 構造方法私有
     */
    private Singleton() {
        System.out.println("建立單例例項...");
    }

    /**
     * 對外提供獲取例項的靜態方法
     */
    public static Singleton getInstance() {
        if (null == singleton) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

從程式碼實現中可以看到,例項並不是在一開始就是初始化的,而是在呼叫 getInstance()方法後才會產生單例,這種模式延遲初始化例項,但它並非是執行緒安全的。

public class SingleTonTest {

    /**
     * 多執行緒模式下測試懶漢模式是否執行緒安全
     *
     * @param args
     */
    public static void main(String[] args) {
        /**
         * 這裡我圖方便,直接用Executors建立執行緒池
         * 阿里巴巴開發手冊是不推薦這麼做的
         */
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 20; i++) {
            executorService.execute(() -> System.out.println(Thread.currentThread().getName() + "::" + Singleton.getInstance()));
        }
    }
}

測試結果截圖:

懶漢式是在執行時載入物件的,所以載入該單例類時會比較快,但是獲取物件會比較慢。且這樣做是執行緒不安全的,如果想要執行緒安全,可以在getInstance()方法加上synchronized 關鍵詞修飾,但這樣會讓我們付出慘重的效率代價。

2.2. 餓漢式

提前建立好例項物件,呼叫效率高,但無法延時載入,容易產生垃圾,執行緒安全。

public class Singleton {

    /**
     * 自我例項化
     */
    private static Singleton singleton = new Singleton();

    /**
     * 構造方法私有
     */
    private Singleton() {
        System.out.println("建立單例例項...");
    }

    /**
     * 對外提供獲取例項的靜態方法
     */
    public static Singleton getInstance() {
        return singleton;
    }
}

2.3. 雙重檢查鎖模式

public class Singleton {

    /**
     * 自我例項化,volatile修飾,保證執行緒間可見
     */
    private volatile static Singleton singleton;

    /**
     * 構造方法私有
     */
    private Singleton() {
        System.out.println("建立單例例項...");
    }

    /**
     * 對外提供獲取例項的靜態方法
     */
    public static Singleton getInstance() {
        // 第一次檢查,避免不必要的例項
        if (singleton == null) {
            // 第二次檢查,同步,避免產生多執行緒的問題
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

由於singleton=new Singleton()物件的建立在JVM中可能會進行重排序,在多執行緒訪問下存在風險,使用volatile修飾signleton例項變數,能禁止指令重排,使得物件在多執行緒間可見,能夠有效解決該問題。

雙重檢查鎖定失敗的問題並不歸咎於 JVM 中的實現 bug,而是歸咎於 Java 平臺記憶體模型。記憶體模型允許所謂的“無序寫入”,這也是這些習語失敗的一個主要原因

2.4. 靜態內部類模式

public class Singleton {
    /**
     * 構造方法私有
     */
    private Singleton() {
        System.out.println("建立單例例項...");
    }

    private static class SingletonInner {
        private static Singleton instance = new Singleton();
    }

    private static Singleton getInstance() {
        return SingletonInner.singleton;
    }
}

這樣寫充分利用靜態內部類的特點——初始化操作和外部類是分開的,只有首次呼叫getInstance()方法時,虛擬機器才載入內部類(SingletonInner.class)並初始化instance, 保證物件的唯一性。

2.5. 列舉單例模式

public enum Singleton {
    INSTANCE 
}

感覺異常簡單,預設列舉類建立的物件都是單例的,且支援多執行緒。

3.單例模式總結

  1. 單例模式優點在於:全域性只會生成單個例項,所以能夠節省系統資源,減少效能開銷。然而也正是因為只有單個例項,導致該單例類職責過重,違背了“單一職責原則”,單例類也沒有抽象方法,會導致比較難以擴充套件。
  2. 以上所有單例模式中,推薦使用靜態內部類的實現,非常直觀,且保證執行緒安全。在《Effective Java》中推薦列舉類,但太簡單了,導致程式碼的可讀性比較差。
  3. 單例模式是建立型模式,反序列化時需要重寫readResovle()方法,以保證例項唯一。

文章首發於本人部落格:www.developlee.top, 轉載請註明出處!

關注公眾號,後臺回覆666, 領取福利:

相關推薦

不管年底工作瞭解下單模式

1. 單例模式 什麼是單例模式?簡言之就是確保定義為單例模式的類在程式中有且只有一個例項。單例模式的特點: 只有一個例項 (只能有一個物件被建立) 自我例項化(類構造器私有) 對外提供獲取例項的靜態方法 2.單例模式的實現 常見的單例模式實現方式有五種: 2.1. 懶漢式 懶漢式(一般也稱之為 飽漢式),

#程式設計師一週衣服被批自稱影響工作網友回到:還好意思說!

程式設計師在人們眼裡就是不會穿衣服的人,格子衫大眼鏡似乎成了程式設計師的代名詞,平時上班穿著拖鞋大褲衩上班就行,這似乎成了一個平常的現象。如果你看到程式設計師穿得整整齊齊西裝革履去上班,你還會覺得他是程式設計師嗎?但是衣品差並不代表不講衛生。 寫這篇文章之前,我

web前端這麼缺人然而還是找工作!我歸結於以下幾點

一:web前端就業要求變高 因為網際網路的發展速度很快,而對於使用者體驗的要求也越來越高,而在網站方面,對於前端的要求肯定也是提高的,就拿天貓為例,每年雙十一大戰,訪問越來越大,這不僅是關乎到後臺資料的處理,對於前端的要求也更高。 兩年前到去年年初,會靜態網

三個月找工作會怎麼辦?

  但是,“降低期望薪資”能否真正吸引面試官或公司?不一定!從公司運營的角度來說,低薪意味著人力成本的節約,但是公司有時候也有這樣的假設:期望薪資低=能力不佳,他們可能會認為你希望通過降低薪資來彌補能力上的短板。所以,對在漫長求職路上“奔波”的求職者而言,工作誠可貴,薪資不可拋!理智得選擇期望薪資範圍、適時放

累死工作而是工作方法

人在職場,每天有如陀螺般忙得轉個不停,大家抱怨著工作苦,工作累,工作辛苦沒的睡。但是仔細思量,如

#程式設計師剛畢業適應工作吃安眠藥入睡難受啊馬飛!

現在的網際網路行業競爭激烈,而應屆畢業生也是最近加入職場,可能也有諸多不適應,公司的業務或者工作強度大,導致一些畢業生可能就很焦慮,要嚴重的甚至要靠吃安眠藥來入睡,但是看到朋友圈大家都在熱熱鬧鬧,自己卻只能躺在出租房的床上,真的很難受。 有想學習java的程式設計師,可來我們的java學習扣

培訓轉行當了程式設計師卻找工作幾萬學費白交了!

  沒做過程式設計師的人都知道,程式設計師工資老高了。於是在這網際網路時代,激發了越來越多的人投身其中就業與創業,除了科班畢業的程式設計師,也有不少其他行業從業者轉行的人員,這些半路轉行的人員,有的是通過自學的,有的則通過花錢上培訓班達到速成的效果。但是,轉行往往意味著要空出一段時間做準備

40歲的碼農找工作原來碼農真的是碗青春飯

有人說,程式設計師真的只能吃青春飯,企業在招聘時會在意程式設計師的年齡,大齡程式設計師一旦離職找工作就會變得艱難。 這不,最近有個關於老齡程式設計師的求職故事: 面對年齡很多程式設計師都好像很焦灼,束手無策一樣,但程式設計師真的是青春飯麼? 其實,程式設計師其實也和其他職業一樣,到

程式設計師的悲哀:年近40找工作中年危機悄然來臨!

君不見,去網際網路公司走一走,你會發現,那些做開發寫程式碼的基本上都是清一色的小夥子,基本上不會見到大齡碼農的身影。 有很多程式設計師笑言:寫程式碼是一個體力活,年紀越大,加班就吃不消了。因此很多碼農會選擇轉型,比如上升到管理層,而大部分的其他人則選擇了轉型。 有一名將近40歲的程式設計師就

5個Excel常用函式幫解決70%的基礎工作會多少呢?

你還在這默默的為不知道如何操作Excel函式技巧而煩惱嗎?雖然說Excel函式確實比較複雜,但是隻要我們熟練的掌握幾個常用的Excel函式,基本上也就可以幫助我們解決70%的基礎工作。 今天小編在這裡為大家分享5個Excel常用函式,學會了這些幫你解決70%的基

php讀取寫入資料庫亂碼如果百度能解決看看這篇吧!!

  php專案是宕下來的,本人也是剛接觸php,但是我要說的是這個php基本關係不大,這個亂碼問題困擾了我好幾天,百度了n多解決方案,發現就呵呵了全是抄來的,還不註明轉載地址,也是服了!百度上的方法我幾乎都試過,修改php.ini檔案啦,修改my.ini檔案啦,還有設定頁面字元編碼集,保持

2018MaxCompute開發者聖誕趴 — 承認吧嚮往的是紅包而是最前沿的大資料技術

大資料開發者都怎麼過聖誕節?一切如常,加班。。。提前下班,回家睡覺。。。給女朋友買個南瓜燈做禮物?OMG!!! Jingle bells,大資料開發者的聖誕時間到~這封聖誕邀請,我想發給所有MaxCompute開發者和大資料愛好者們,搞個Party,你可別說你要改bug, 發幾波紅包,你可別說你眼裡只有co

工作有感只是工作還是戰場

2018年11月09日 12:59:45 xiaoxiru 閱讀數:9 個人分類: 雜文

40歲的程式設計師找工作原來碼農真的是碗青春飯

有人說,程式設計師真的只能吃青春飯,企業在招聘時會在意程式設計師的年齡,大齡程式設計師一旦離職找工作就會變得艱難。這不,最近有個關於老齡程式設計師的求職故事: 面對年齡很多程式設計師都好像很焦灼,束手無策一樣,但程式設計師真的是青春飯麼?其實,程式設計師其實也和其他職業一樣,到底是

學員會診之04:為什麼找工作

我有一段時間看到文同學和潘同學比較的窩火,明明學的也還不錯,卻老是跟我說找不到工作。 先說說文同學。文同學很有意思,剛畢業那會面試機會還蠻多,並且沒兩天還拿下一個offer:某個小軟體公司讓他去做架構師~~。當然他面試的職位是Java工程師,一下子沒發揮好,吹的太厲害了,對方直接讓他上來做架構師~~~。那他

年底根本招人跳槽就是和自己過不去!這話能信嗎?

        一年中求職的最佳時間是什麼時候?這個問題的傳統答案一般為“金三銀四”、“金九銀十”,即一年中的3月、4月、9月、10月,如今是否依舊如此呢,而年底就是不適合跳槽的災難時機?錦囊菌想從不同人群的不同視角來講起:    首先對應屆生來說,根據前程無憂和應屆生

大齡程序員找工作程序員真的是吃青春飯的嗎?

初中 工資 整理 不同 人才 為我 創業者 也有 發的 程序員這行業就是吃青春飯的,於是也有許多這個行業的新手開始追問,程序員真的是吃青春飯的嗎?在這裏,我借用一位老程序員的話:程序員不是年紀大的都轉行了,而是技術差的都被淘汰了。當然,如果一味這樣說也過於偏頗了。所以,今天

丟擲這8個問題檢驗一下到底會會ThreadLocal來摸個底~

0、問題 和Synchronized的區別 儲存在jvm的哪個區域 真的只是當前執行緒可見嗎 會導致記憶體洩漏麼 為什麼用Entry陣列而不是Entry物件 你學習的開源框架哪些用到了ThreadLocal ThreadLocal裡的物件一定是執行緒安全的嗎 筆試題 一、概述 1、官方術語 ThreadL

小猿理財:能讓躺賺的投資品種瞭解下!

我們是如何在股市上虧錢的? 前面我們說了,從長期來看,投資股票是收益率最高的投資品種,因為它的背後代表了公司的價值,所以它的增值速度也是最快的。只要我們買入這些股票,同樣可以獲得最快的增值速度。 為什麼那麼多人在股票市場上虧錢呢?你可能覺得,只有別人虧錢,你才能賺錢呀!不然怎麼能