1. 程式人生 > >Java單例模式(Singleton)以及實現

Java單例模式(Singleton)以及實現

一. 什麼是單例模式

因程式需要,有時我們只需要某個類同時保留一個物件,不希望有更多物件,此時,我們則應考慮單例模式的設計。

二. 單例模式的特點

1. 單例模式只能有一個例項。

2. 單例類必須建立自己的唯一例項。

3. 單例類必須向其他物件提供這一例項。

三. 單例模式VS靜態類

在知道了什麼是單例模式後,我想你一定會想到靜態類,“既然只使用一個物件,為何不乾脆使用靜態類?”,這裡我會將單例模式和靜態類進行一個比較。

1. 單例可以繼承和被繼承,方法可以被override,而靜態方法不可以。

2. 靜態方法中產生的物件會在執行後被釋放,進而被GC清理,不會一直存在於記憶體中。

3. 靜態類會在第一次執行時初始化,單例模式可以有其他的選擇,即可以延遲載入。

4. 基於2, 3條,由於單例物件往往存在於DAO層(例如sessionFactory),如果反覆的初始化和釋放,則會佔用很多資源,而使用單例模式將其常駐於記憶體可以更加節約資源。

5. 靜態方法有更高的訪問效率。

6. 單例模式很容易被測試。

幾個關於靜態類的誤解:

誤解一:靜態方法常駐記憶體而例項方法不是。

實際上,特殊編寫的例項方法可以常駐記憶體,而靜態方法需要不斷初始化和釋放。

誤解二:靜態方法在堆(heap)上,例項方法在棧(stack)上。

實際上,都是載入到特殊的不可寫的程式碼記憶體區域中。

靜態類和單例模式情景的選擇:

情景一:不需要維持任何狀態,僅僅用於全域性訪問,此時更適合使用靜態類。

情景二:需要維持一些特定的狀態,此時更適合使用單例模式。

四. 單例模式的實現

1. 懶漢模式

public class SingletonDemo {
    private static SingletonDemo instance;
    private SingletonDemo(){

    }
    public static SingletonDemo getInstance(){
        if(instance==null){
            instance=new SingletonDemo();
        }
        return instance;
    }
}

如上,通過提供一個靜態的物件instance,利用private許可權的構造方法和getInstance()方法來給予訪問者一個單例。

缺點是,沒有考慮到執行緒安全,可能存在多個訪問者同時訪問,並同時構造了多個物件的問題。之所以叫做懶漢模式,主要是因為此種方法可以非常明顯的lazy loading。

針對懶漢模式執行緒不安全的問題,我們自然想到了,在getInstance()方法前加鎖,於是就有了第二種實現。

2. 執行緒安全的懶漢模式

public class SingletonDemo {
    private static SingletonDemo instance;
    private SingletonDemo(){

    }
    public static synchronized SingletonDemo getInstance(){
        if(instance==null){
            instance=new SingletonDemo();
        }
        return instance;
    }
}

然而併發其實是一種特殊情況,大多時候這個鎖佔用的額外資源都浪費了,這種打補丁方式寫出來的結構效率很低。

3. 餓漢模式

public class SingletonDemo {
    private static SingletonDemo instance=new SingletonDemo();
    private SingletonDemo(){

    }
    public static SingletonDemo getInstance(){
        return instance;
    }
}

直接在執行這個類的時候進行一次loading,之後直接訪問。顯然,這種方法沒有起到lazy loading的效果,考慮到前面提到的和靜態類的對比,這種方法只比靜態類多了一個記憶體常駐而已。

4. 靜態類內部載入

public class SingletonDemo {
    private static class SingletonHolder{
        private static SingletonDemo instance=new SingletonDemo();
    }
    private SingletonDemo(){
        System.out.println("Singleton has loaded");
    }
    public static SingletonDemo getInstance(){
        return SingletonHolder.instance;
    }
}

使用內部類的好處是,靜態內部類不會在單例載入時就載入,而是在呼叫getInstance()方法時才進行載入,達到了類似懶漢模式的效果,而這種方法又是執行緒安全的。

5. 列舉方法

enum SingletonDemo{
    INSTANCE;
    public void otherMethods(){
        System.out.println("Something");
    }
}

Effective Java作者Josh Bloch 提倡的方式,在我看來簡直是來自神的寫法。解決了以下三個問題:

(1)自由序列化。

(2)保證只有一個例項。

(3)執行緒安全。

如果我們想呼叫它的方法時,僅需要以下操作:

public class Hello {
    public static void main(String[] args){
        SingletonDemo.INSTANCE.otherMethods();
    }
}

這種充滿美感的程式碼真的已經終結了其他一切實現方法了。

6. 雙重校驗鎖法

public class SingletonDemo {
    private volatile static SingletonDemo instance;
    private SingletonDemo(){
        System.out.println("Singleton has loaded");
    }
    public static SingletonDemo getInstance(){
        if(instance==null){
            synchronized (SingletonDemo.class){
                if(instance==null){
                    instance=new SingletonDemo();
                }
            }
        }
        return instance;
    }
}

接下來我解釋一下在併發時,雙重校驗鎖法會有怎樣的情景:

STEP 1. 執行緒A訪問getInstance()方法,因為單例還沒有例項化,所以進入了鎖定塊。

STEP 2. 執行緒B訪問getInstance()方法,因為單例還沒有例項化,得以訪問接下來程式碼塊,而接下來程式碼塊已經被執行緒1鎖定。

STEP 3. 執行緒A進入下一判斷,因為單例還沒有例項化,所以進行單例例項化,成功例項化後退出程式碼塊,解除鎖定。

STEP 4. 執行緒B進入接下來程式碼塊,鎖定執行緒,進入下一判斷,因為已經例項化,退出程式碼塊,解除鎖定。

STEP 5. 執行緒A初始化並獲取到了單例例項並返回,執行緒B獲取了線上程A中初始化的單例。

理論上雙重校驗鎖法是執行緒安全的,並且,這種方法實現了lazyloading。

相關推薦

Java模式(Singleton)以及實現

一. 什麼是單例模式 因程式需要,有時我們只需要某個類同時保留一個物件,不希望有更多物件,此時,我們則應考慮單例模式的設計。 二. 單例模式的特點 1. 單例模式只能有一個例項。 2. 單例類必須建立自己的唯一例項。 3. 單例類必須向其他物件提供這一例項。 三. 單例模式VS靜態類 在知道了什麼是單例模式後

Java模式幾種實現方式

開始 名稱 常量 就是 多線程開發 靜態代碼塊 浪費 ack 多線程同步 在平時的工作、學員的學習以及面試過程中,單例模式作為一種常用的設計模式,會經常被面試官問到,甚至筆試會要求學員現場默寫,下面將會就單例模式的實現思路和幾種常見的實現方式進行簡單的分享。

Java模式的正確實現

Java單例模式 單例的好處 單例模式適合於應用中頻繁建立的物件,如果是重量級的物件,更應該使用單例模式。比如配置檔案,如果不採用單例模式的話,每個配置檔案物件的內容都是一樣的,建立重複的物件就會浪費寶貴的記憶體,所以有必要使用單例模式,達到效能的提升,

淺談java模式——優點以及為什麼使用到synchronized

首先 說一下單例模式的好處:減少系統資源的消耗.因為這種工具類基本上貫穿程式始終,必然會頻繁呼叫.如果每一次呼叫都要重新生成例項,帶來的就是 在記憶體堆中,分配一部分記憶體空間.所以這種模式會提高程式的執行速度,減少資源消耗。 可能對於沒有理解單例模式的小夥

設計模式之——模式(Singleton)的實現、優缺點和常見應用場景

單例模式(Singleton)也叫單態模式,是設計模式中最為簡單的一種模式,甚至有些模式大師都不稱其為模式,稱其為一種實現技巧,因為設計模式講究物件之間的關係的抽象,而單例模式只有自己一個物件,也因此有些設計大師並把把其稱為設計模式之一。 好多沒怎麼使用過的人可能會想,單例模式感覺不怎麼用到,實際的應

Java 模式幾種實現的差別

單例模式確保某個類只有一個例項,而且自行例項化並向整個系統提供這個例項。 思路是通過將該類的構造方法設為private,那麼在其他類中不能直接例項化該類。那麼為了得到該類的例項,需要有public的static方法來返回該類的例項。(之所以static是為了可以直接用

Java模式(singleton)

ron 好聽 on() == sin 如果 odin 如同 可能 為什麽需要單例?只因為國家的獨生子女政策(當然現在可以生2個) 單例是一個很孤獨的物種,因為它的類裏面做多只有也僅只有它一個。 常見的是懶漢及餓漢模式, 1.懶漢,為什麽這麽叫,看看英文,原為lazy loa

設計模式模式 Singleton實現

-- throw return null mage demo1 nbsp 定義 所在 餓漢式 餓漢式單例模式,static變量會在類裝載時初始化,此時也不會涉及多個線程對象訪問該對象的問題。虛擬機保證只會裝載一次該類,肯定不會發生並發訪問的問題,

Java模式 多種實現方式

main 概念 ron system sta ava 實現 args == 一:通過靜態私有成員實現單例模式 (1):私有化構造函數 (2):new靜態實例屬性對象,加鎖。 單例類: package SinglePag; /* * 構造函數私有化,結合鎖+靜態的概念 實

java模式模式(Singleton)有什麽意義?

ESS 兩張 oid 什麽 else 不能 spa lse new 8.單態模式或單例模式(Singleton) (視頻下載) (全部書籍)單態模式有什麽用呢?想一下Adobe Photoshop ,處理兩張圖,會啟動兩個photoshop嗎?多耗費內存呀! ( Cons

JAVA設計模式-模式(Singleton)線程安全與效率

保存 ring 使用方法 部分 rac cheng 原因 cts 要求 一,前言   單例模式詳細大家都已經非常熟悉了,在文章單例模式的八種寫法比較中,對單例模式的概念以及使用場景都做了很不錯的說明。請在閱讀本文之前,閱讀一下這篇文章,因為本文就是按照這篇文章中的八種單例模

JAVA模式實現詳解

單例模式的特點 類的內部包括待返回的類的例項,為private static型別 類的建構函式為私有建構函式,以防止在其他類中例項化,private的作用是防止在其他類中用建構函式建立該類的例項 提供一個獲取例項的靜態方法 單例模式1:飽漢模式+考慮了執

Java模式實現的幾種方法

package offer; public class Test02 { /** * 01 餓漢模式 執行緒安全 */ public static class Singleton{ private final static Singleton

java模式雙重檢驗鎖的優缺點?還有哪些實現方式?列舉一些使用場景

2018年7月18日,在專案程式碼中看到單例模式,總結一下單例模式的知識點. 單例模式的概念: 在應用程式的生命週期中,在任意時刻,引用某個類的例項都是同一個.在一個系統中有些類只需要有一個全域性物件,統一管理系統行為和執行某些操作.例如在使用hibernate時,ses

模式(Singleton Pattern)的6種實現

摘要 在我們日常的工作中經常需要在應用程式中保持一個唯一的例項,如:IO處理,資料庫操作等,由於這些物件都要佔用重要的系統資源,所以我們必須限制這些例項的建立或始終使用一個公用的例項,這就是我們今天要介紹的——單例模式(Singleton Pattern)。 概念 單例

JAVA設計模式-模式(Singleton)執行緒安全與效率

一,前言   單例模式詳細大家都已經非常熟悉了,在文章單例模式的八種寫法比較中,對單例模式的概念以及使用場景都做了很不錯的說明。請在閱讀本文之前,閱讀一下這篇文章,因為本文就是按照這篇文章中的八種單例模式進行探索的。   本文的目的是:結合文章中的八種單例模式的寫法,使用實際的示例,來演示執行緒安全和效率  

Java設計模式模式(Singleton)

單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。 這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可

三維分析Java模式實現方式的優缺點

一、餓漢式(Eager Singleton) package main.singleton; /** * Created by leboop on 2018/11/27. * 宣告為final,不可被繼承 */ public final class EagerSingleton {

Javasingleton模式

單例模式,是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中,應用該模式的類一個類只有一個例項。即一個類只有一個物件例項。 單例模式的一個例子: 1、建立一個Singleton類 public class SingleO

Java模式的三種實現方式

單例模式之餓漢式 在類載入時就初始化一個類物件,使用靜態載入,但是在類載入時就例項化物件,單例物件較大的時候會影響系統載入速度。 public class Singleton { private Singleton() { Sy