手寫單例模式

2021-02-15 你應該了解的Java
手寫單例模式為什麼要有單例模式:

在編程中,有些場景,是這樣的:       有些對象我們只需要一個,比如線程池對象、緩存、系統全局配置文件對象等。       這樣我們就保證一個在全局使用的類不被頻繁的創建與銷毀,節省系統資源。

實現單例模式的三大要點:

1、首先要確保全局只有一個類的實例。      

               因此至少類的構造器要私有化。

        2、單例的類只能自己創建自己的實例。    

              因為構造器私有了,但是還要有一個實例,所有就只能自己創建。

        3、單例類必須能夠提供自己的唯一實例給其他類。      

              因此要有一個公共的方法能返回該單例類的唯一實例。

單例的幾種實現1、懶漢模式(單線程使用)

--懶漢式就是不在系統加載時就創建類的單例,而是在第一次使用實例的時候再創建。--多線程禁止使用。延遲加載(LazyLoading)很明顯嚴格來講不算單例模式,因為線程不安全,多線程下,可能產生多個對象。不是單例。public class Lanhandanli{

//第一步靜態私有化對象
private static Lanhandanli instance = null;
//第二步私有化空參構造
privateLanhandanli(){}
//第三步提供獲取對象方法
piublic static Lanhandanli getInstance(){
//判斷對象是否為null,如果為空就創建
if(instance==null){
instance = new Lasnhandanli();
}
return instance;
}

}

2、餓漢模式--靜態常量方式

--在加載類的時候就會創建類的單例,並保存在類中。--靜態常量方式(線程安全--類加載是就初始化實例,避免了多線程同步問題。天然線程安全)public class Ehandanli{

private static finall Ehandanli instance = new Ehandanli();
private Ehandanli(){}
public static Ehandanli getInstance(){
return Ehandanli;
}

}

3、餓漢模式--靜態代碼塊方式

--靜態代碼塊方式(線程安全)其實就是上面靜態常量餓漢式 實現上稍微變動一下,將類的實例化放到了靜態代碼塊中而已。public class Ehandanli{

private static finall Ehandanli instance;
static {
      instance = new Ehandanli();
}
private Ehandanli(){}
public static Ehandanli getInstance(){
return Ehandanli;
}

}

4、懶漢模式--synchronized同步鎖

--synchronized同步鎖(線程安全--與上面懶漢模式實現唯一不同的是,獲取實例getInstance()方法上加了同步鎖,保證線程多線程下單例。但是效率有所折損,不過還好)public class Lanhandanli{

//第一步靜態私有化對象
private static Lanhandanli instance = null;
//第二步私有化空參構造
privateLanhandanli(){}
//第三步提供獲取對象方法
piublic static synchronized Lanhandanli getInstance(){
//判斷對象是否為null,如果為空就創建
if(instance==null){
instance = new Lasnhandanli();
}
return instance;
}

}

5、懶漢模式--雙重校驗鎖--DCL

--雙重校驗鎖--DCL,即 double-checked locking使用到(volatile and synchronized)此種實現中不用每次需要獲得鎖,減少了獲取鎖和等待的事件。注意volatile關鍵字的使用,保證了各線程對singleton靜態實例域修改的可見性。public class Lanhandanli{

//第一步靜態私有化對象
private volatile static Lanhandanli instance = null;
//第二步私有化空參構造
privateLanhandanli(){}
//第三步提供獲取對象方法
piublic static synchronized Lanhandanli getInstance(){
//判斷對象是否為null,如果為空就創建
if(instance==null){
instance = new Lasnhandanli();
}
return instance;
}

//第一步靜態私有化對象
private volatile static Lanhandanli instance = null;
//第二步私有化空參構造
privateLanhandanli(){}
//第三步提供獲取對象方法
piublic static Lanhandanli getInstance(){
if(instance==null){
synchronized(LanHandanli.class){
if(instance == null){
instance = new Lasnhandanli();
}
}
}
return instance;
}

}描述:這種方式稱為雙重檢查鎖(Double-Check Locking),需要注意的是,如果使用雙重檢查鎖定來實現懶漢式單例類,需要在靜態成員變量instance之前增加修飾符volatile,被volatile修飾的成員變量可以確保多個線程都能夠正確處理,且該代碼只能在JDK 1.5及以上版本中才能正確執行。由於volatile關鍵字會屏蔽Java虛擬機所做的一些代碼優化,可能會導致系統運行效率降低,因此即使使用雙重檢查鎖定來實現單例模式也不是一種完美的實現方式。

6、懶漢模式--靜態內部類實現單例

--靜態內部類實現單例(線程安全、效率高)zhe這種方式下Singleton類被加載了,inatance不一定被初始化。因為SingletonHolder累沒有被主動使用,只有通過顯示調用getInstance方法時,才會顯示裝載SingletonHolder類,從而實例化instance.注意內部類SingletonHolder要用static修飾且其中的的靜態變量instance必須睡final修飾的。public calss Singleton{ //內部類 private static class SingletonHolder { private static final Singleton instance = new Singleton(); }

private Singleton(){};

public static final Singleton getInstance(){
return SingletonHolder.instance;
}

}描述:餓漢式單例類不能實現延遲加載,不管將來用不用始終佔據內存;懶漢式單例類線程安全控制煩瑣,而且性能受影響。可見,無論是餓漢式單例還是懶漢式單例都存在這樣那樣的問題,有沒有一種方法,能夠將兩種單例的缺點都克服,而將兩者的優點合二為一呢?答案是:Yes!下面我們來學習這種更好的被稱之為Initialization Demand Holder (IoDH)的技術。在IoDH中,我們在單例類中增加一個靜態(static)內部類,在該內部類中創建單例對象,再將該單例對象通過getInstance()方法返回給外部使用。由於靜態單例對象沒有作為Singleton的成員變量直接實例化,因此類加載時不會實例化Singleton,第一次調用getInstance()時將加載內部類SingletonHolder,在該內部類中定義了一個static類型的變量instance,此時會首先初始化這個成員變量,由Java虛擬機來保證其線程安全性,確保該成員變量只能初始化一次。由於getInstance()方法沒有任何線程鎖定,因此其性能不會造成任何影響。通過使用IoDH,我們既可以實現延遲加載,又可以保證線程安全,不影響系統性能,不失為一種最好的Java語言單例模式實現方式**(其缺點是與程式語言本身的特性相關,很多面向對象語言不支持IoDH)

相關焦點

  • 設計模式:單例模式
    基本概念1.1 原理單例模式可以說是所有設計模式中最簡單的一個了,這裡我們先直接給出它的概念然後再對它進行詳細的講解。單例模式就是:一個類只能有一個實例,並提供對該實例的全局訪問點。通俗地說,就是一個類只能創建一個對象,並且在程序的任何地方都能夠訪問到該對象。在某些情況下一些類只需要一個實例就夠了,我們以一個簡化的文件管理器作為例子來說明。
  • 單例模式襲來
    吹一波單例模式❝確保某個類只有一個實例,而且自行實例化並向整個系統提供整個實例。說白了,就是"獨苗"!什麼是"自行實例化"?就是整個實例是在類內部自己創建的,不是在別的類中創建的。❞單例誰都會寫,而且五花八門,且隨洒家來瞅瞅。
  • Python設計模式之單例模式
    什麼場景會用到單例模式呢?就是在系統工程中只想創建單個實例對象,比如資料庫連接池,Redis連接池,服務監控中心等。這個場景下,如果存在多個實例對象,那麼會有無法預測的異常。同時,在設計單例模式時,需要考慮的很重要的因素就是並發性,即多線程調用時是否會存在多個線程。那麼,如何設計使用單例模式呢?
  • Android設計模式(1)——單例模式
    單例模式使用的場景確保某個類有且只有一個對象的場景,避免產生多個對象消耗過多的資源,或者某種類型對象只應該有且只有一個,例如,創建一個對象需要消耗的資源過多,,如要訪問IO和資料庫等資源,這時就需要考慮使用單例模式。
  • 設計模式一:單例模式
    什麼是單例模式單例模式是指系統中的某個類只能有一個對象實例。
  • 深入淺出js單例模式
    何為單例模式?顧名思義,單例模式就是保證一個類僅有一個實例,也就是創建出來的兩個實例必須相等!
  • Java的單例模式
    一、什麼是單例模式?
  • Java單例模式深入詳解
    我主要是應用在使用普通類模擬枚舉類型裡,後來發現這就是傳說中的單例模式。構造函數弄成private 就是單例模式,即不想讓別人用new 方法來創建多個對象,可以在類裡面先生成一個對象,然後寫一個public static方法把這個對象return出去。
  • 為什麼要用單例模式?
    我們在編程中最常用的模式就是單例模式了,然而單例模式都用在什麼場合?為什麼不用靜態方法而要用單例模式呢?
  • 深入解析單例模式的七種實現
    來源:http://t.cn/E4J3ffX什麼是單例模式如何實現單例模式呢?單例模式的七種實現總結什麼是單例模式什麼是單例模式呢?我們引用一下維基百科:單例模式,也叫單子模式,是一種常用的軟體設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行為。
  • PHP 單例模式的解析和實戰
    1、含義   作為對象的創建模式,單例模式確保某一個類只有一個實例,而且自行實例化並向整個系統全局地提供這個實例。它不會創建實例副本,而是會向單例類內部存儲的實例返回一個引用。2、單例模式的三個要點:(1).
  • Java 實現單例模式的 9 種方法
    什麼是單例模式二. 單例模式的特點三. 單例模式VS靜態類四. 單例模式的實現一. 什麼是單例模式因進程需要,有時我們只需要某個類同時保留一個對象,不希望有更多對象,此時,我們則應考慮單例模式的設計。二. 單例模式的特點單例模式只能有一個實例。單例類必須創建自己的唯一實例。
  • 【設計模式】各個擊破單例模式的8種寫法
    單例模式在一個系統開發過程中,我們在基於節省內存資源、保證數據內容的一致性的考慮上,往往需要對某些類要求只能創建一個實例,即「保證類只有一個實例」的設計模式就是單例模式。比如我們遇到過的各種Manager管理類,各種Factory工廠類;Spring 框架應用中的 ApplicationContext、資料庫中的連接池等也都是單例模式。本文旨在淺析一下單例模式的寫法。單例模式的8種寫法1.
  • 設計模式大冒險第四關:單例模式,如何成為你的「唯一」
    今天這篇文章我們就來一起好好學習一下單例模式。讓我們開始吧。單例模式的介紹首先我們先來看一下單例模式的定義是什麼。所謂的單例模式,就是指對於一個具體的類來說,它有且只有一個實例,這個類負責創建唯一的實例,並且對外提供一個全局的訪問接口。
  • 什麼是python單例模式,看完你就知道了
    1、什麼是單例模式讓所有類在實例化時,指向同一個內存地址,稱之為單例模式 PS:無論產生多少個對象,都會指向 單個 實例當在確定 "類中的屬性與方法不變" 需要反覆調用類時,會產生不同的對象,也會產生不同的內存地址,最終造成資源的浪費
  • 單例(Singleton)設計模式及在Java中的實現
    設計模式(Design Pattern)是在經過大量的實踐後總結出來,並且經過理論化分析優選出的編程風格、代碼結構以及解決問題的思考方式。一、何為單例模式?在編程世界中,目前經典的共有23種設計模式,單例模式只是其中一種。
  • 面向對象軟體設計模式(1)--單例模式(Singleton)
    在電影的拍攝過程中,可能會設計多個片場,導演需要對不同的演員進行分別指導,但所有演員導演都是同一個人,「把導演叫過來」 這個過程可以視為單例模式獲取實例的過程模式分析先來看最簡單的寫法public class Single { private static Single instance; public static Single getInstance()
  • 大話設計模式之愛你一萬年:第二章 創建型模式:單例模式::我的女朋友只有你一個:3.4.5.單例模式的實現-餓漢/靜態/枚舉
    大話設計模式之愛你一萬年:第一章 設計模式基本概念:大話設計模式之愛你一萬年:第一章 設計模式基本概念:2.GoF的23種設計模式的分類和功能大話設計模式之愛你一萬年:第一章 設計模式基本概念:3.設計模式的六大原則大話設計模式之愛你一萬年:第二章 創建型模式:單例模式::我的女朋友只有你一個:1.單例模式的基本概念
  • 一文帶你讀懂單例模式
    單例模式單例模式可以說是設計模式中最簡單的一個了,它屬於創建型模式,其定義如下:單例模式確保某個類只有一個實例,而且自行實例化並向整個系統提供這個實例。在應用這個模式時,單例對象的類必須保證只有一個實例存在。許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行為。
  • java設計模式中的單例模式,收藏起來慢慢看!
    在java中,單例模式算是比較基礎和簡單的,今天就來簡單聊聊什麼是單例模式。比如說,一個應用程式中,某個類的實例對象只有一個,而我們沒有辦法new,因為構造器已經被private聲明了,通過getInstance()的方法可以獲取它們的實例。