1. 程式人生 > >Java 單例模式幾種實現的差別

Java 單例模式幾種實現的差別

單例模式確保某個類只有一個例項,而且自行例項化並向整個系統提供這個例項。

思路是通過將該類的構造方法設為private,那麼在其他類中不能直接例項化該類。那麼為了得到該類的例項,需要有public的static方法來返回該類的例項。(之所以static是為了可以直接用類名來呼叫該方法,不然的話沒有該類的例項,無法呼叫該類的非static方法)

單例模式有以下特點:1、單例類只能有一個例項。  2、單例類必須自己建立自己的唯一例項。  3、單例類必須給所有其他物件提供這一例項。

單例模式主要有以下三種實現方式:懶漢式單例、餓漢式單例、登記式單例。下面來看程式碼示例:

一、懶漢式單例

  1. //懶漢式單例類.在第一次呼叫的時候例項化自己 
  2. publicclass Singleton {  
  3.     private Singleton() {}  
  4.     privatestatic Singleton single=null;  
  5.     //靜態工廠方法 
  6.     publicstatic Singleton getInstance() {  
  7.          if (single == null) {    
  8.              single = new Singleton();  
  9.          }    
  10.         return single;  
  11.     }  
  12. }  

懶漢式其實是一種比較形象的稱謂。既然懶,那麼在建立物件例項的時候就不著急。會一直等到馬上要使用物件例項的時候才會建立,懶人嘛,總是推脫不開的時候才會真正去執行工作,因此在裝載物件的時候不建立物件例項。

懶漢式是典型的時間換空間,就是每次獲取例項都會進行判斷,看是否需要建立例項,浪費判斷的時間。當然,如果一直沒有人使用的話,那就不會建立例項,則節約記憶體空間。

二、餓漢式單例
  1. //餓漢式單例類.在類初始化時,已經自行例項化 
  2. publicclass Singleton1 {  
  3.     private Singleton1() {}  
  4.     privatestaticfinal Singleton1 single = new Singleton1();  
  5.     //靜態工廠方法 
  6.     publicstatic Singleton1 getInstance() {  
  7.         return
     single;  
  8.     }  
  9. }  

餓漢式也是一種比較形象的稱謂。既然餓,那麼在建立物件例項的時候就比較著急,餓了嘛,於是在裝載類的時候就建立物件例項。餓漢式是典型的空間換時間,當類裝載的時候就會建立類的例項,不管你用不用,先創建出來,然後每次呼叫的時候,就不需要再判斷,節省了執行時間。


三、登記式單例
  1. //類似Spring裡面的方法,將類名註冊,下次從裡面直接獲取。
  2. publicclass Singleton3 {  
  3.     privatestatic Map<String,Singleton3> map = new HashMap<String,Singleton3>();  
  4.     static{  
  5.         Singleton3 single = new Singleton3();  
  6.         map.put(single.getClass().getName(), single);  
  7.     }  
  8.     //保護的預設構造子
  9.     protected Singleton3(){}  
  10.     //靜態工廠方法,返還此類惟一的例項
  11.     publicstatic Singleton3 getInstance(String name) {  
  12.         if(name == null) {  
  13.             name = Singleton3.class.getName();  
  14.             System.out.println("name == null"+"--->name="+name);  
  15.         }  
  16.         if(map.get(name) == null) {  
  17.             try {  
  18.                 map.put(name, (Singleton3) Class.forName(name).newInstance());  
  19.             } catch (InstantiationException e) {  
  20.                 e.printStackTrace();  
  21.             } catch (IllegalAccessException e) {  
  22.                 e.printStackTrace();  
  23.             } catch (ClassNotFoundException e) {  
  24.                 e.printStackTrace();  
  25.             }  
  26.         }  
  27.         return map.get(name);  
  28.     }  
  29.     //一個示意性的商業方法
  30.     public String about() {      
  31.         return"Hello, I am RegSingleton.";      
  32.     }      
  33.     publicstaticvoid main(String[] args) {  
  34.         Singleton3 single3 = Singleton3.getInstance(null);  
  35.         System.out.println(single3.about());  
  36.     }  
  37. }  
登記式單例實際上維護了一組單例類的例項,將這些例項存放在一個Map(登記薄)中,對於已經登記過的例項,則從Map直接返回,對於沒有登記的,則先登記,然後返回。

執行緒安全問題

上文中懶漢式單例的程式碼是執行緒不安全的。為了執行緒安全,可以採用以下方法:

1、在getInstance方法上加synchronized

  1. publicstaticsynchronized Singleton getInstance() {  
  2.          if (single == null) {    
  3.              single = new Singleton();  
  4.          }    
  5.         return single;  
  6. }  
2、雙重檢查鎖定
  1. publicstatic Singleton getInstance() {  
  2.         if (singleton == null) {    
  3.             synchronized (Singleton.class) {    
  4.                if (singleton == null) {    
  5.                   singleton = new Singleton();   
  6.                }    
  7.             }    
  8.         }    
  9.         return singleton;   
  10.     }  
3、靜態內部類
  1. publicclass Singleton {  
  2.     private Singleton(){}  
  3.     /** 
  4.      *    類級的內部類,也就是靜態的成員式內部類,該內部類的例項與外部類的例項 
  5.      *    沒有繫結關係,而且只有被呼叫到時才會裝載,從而實現了延遲載入。 
  6.      */
  7.     privatestaticclass SingletonHolder{  
  8.         /** 
  9.          * 靜態初始化器,由JVM來保證執行緒安全 
  10.          */
  11.         privatestatic Singleton instance = new Singleton();  
  12.     }  
  13.     publicstatic Singleton getInstance(){  
  14.         return SingletonHolder.instance;  
  15.     }  
  16. }  

當getInstance方法第一次被呼叫的時候,它第一次讀取SingletonHolder.instance,導致SingletonHolder類得到初始化;而這個類在裝載並被初始化的時候,會初始化它的靜態域,從而建立Singleton的例項,由於是靜態的域,因此只會在虛擬機器裝載類的時候初始化一次,並由虛擬機器來保證它的執行緒安全性。

這個模式的優勢在於,getInstance方法並沒有被同步,並且只是執行一個域的訪問,因此延遲初始化並沒有增加任何訪問成本。

另外就靜態內部類中的三個static說明如下:

  1. publicstatic Singleton getInstance(){  
  2. return SingletonHolder.instance;}  

中的static是為了可以用類名直接呼叫getInstance方法,所以必須為static。那麼該方法內的成員變數也必須為static,否則那個成員變數就要用類的例項來訪問了,這顯然和通過類直接訪問不相符。

  1. privatestatic Singleton instance = new Singleton();  

中的static是因為instance必須為static才可以在getInstance方法中出現。

  1. publicstatic Singleton getInstance()  

中的static是因為若內部類中出現靜態成員變數,則該內部類必為靜態內部類。


最後來看一個單例模式應用的例子有助於理解:

  1. publicclass TMain{  
  2.     publicstaticvoid main(String[] args){  
  3.         Singleton s1=Singleton.getInstance();  
  4.         s1.setName("libai");  
  5.         Singleton s2=Singleton.getInstance();  
  6.         s2.setName("dufu");  
  7.         System.out.println(s1.getName());  
  8.         System.out.println(s2.getName());  
  9.         if(s1==s2){  
  10.             System.out.println("是同一個物件");  
  11.         }else{  
  12.             System.out.println("不是同一個物件");  
  13.         }  
  14.     }  
  15. }  
  16. class Singleton{  
  17.     /* 私有構造方法,防止被例項化 */
  18.     private Singleton() {    
  19.     }    
  20.     private String name;  
  21.     publicvoid setName(String s){  
  22.         this.name=s;  
  23.     }  
  24.     public String getName(){  
  25.         returnthis.name;  
  26.     }  
  27.     /*餓漢式單例*/
  28.     privatestaticfinal Singleton instance = new Singleton();  
  29.     /* 獲取例項 */
  30.     publicstatic

    相關推薦

    Java 模式實現差別

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

    Java模式實現方式

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

    模式實現方式

    size ron jdk null singleton bsp 還要 一個 fin 1、餓漢式:靜態常量 特點:單例的實例被聲明成static和final變量了,在第一次加載類到內存中時就會初始化,所以會創建實例本身是線程安全的 public class Sin

    高併發下最全執行緒安全的模式實現

    為了節約系統資源,有時需要確保系統中某個類只有唯一一個例項,當這個唯一例項建立成功之後,我們無法再建立一個同類型的其他物件,所有的操作都只能基於這個唯一例項。 但是餓漢式單例類不能實現延遲載入,不管將來用不用始終佔據記憶體;懶漢式單例類執行緒安全控制煩瑣,而且效能受影響。可

    Android 模式實現方式及簡析

    一.定義: 確保某一個類只有一個例項,而且自行例項並向整個系統提供這個例項 二.使用場景: 避免產生過多的物件消耗過多的資源,或者某種型別的物件只應該有且只有一個。例如,建立一個物件需要消耗的資源過多,如訪問資料庫或者IO 資源。 三.實現單例模式的關鍵

    模式寫法

    遺憾 想象 develop 由於 tcl loader adr 希望 線程不安全 第一種(懶漢,線程不安全): Java代碼 public class Singleton { private static Singleton instance;

    java寫法

    多線程 ibm 顯示 詳細 作者 jdk1.5 需要 fin serial 轉載出處:http://cantellow.javaeye.com/blog/838473 第一種(懶漢,線程不安全): 1 public class Singleton { 2 pr

    java 模式5寫法

    浪費 get public color ring 缺點 threads 構造函數 java 單例模式 學習整理 飽漢模式(懶漢模式) 1 // 飽漢 2 // UnThreadSafe 3 public class Singleton1 { 4 private

    C++之智慧指標和普通指標模式實現

    1  問題 實現c++的單例模式,這裡測試分別寫了通過智慧指標返回物件和普通返回指標     2  程式碼測試 include <iostream> #include <mutex> #include <m

    Java模式的正確實現

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

    模式6實現方式

    一:餓漢式public class MyObject { // 立即載入方式==餓漢模式 private static MyObject myObject = new MyObject();

    模式——六實現方式(懶漢、餓漢、雙重檢驗鎖、靜態內部類、列舉)

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

    JAVA模式6寫法(附反射破壞

    java中單例模式是一種常見的設計模式,單例模式的寫法有多種,這裡主要介紹6種寫法:餓漢式單例、懶漢式單例3個、靜態內部類,列舉。   單例模式有以下特點:   1、單例類只能有一個例項。   2、單例類必須自己建立自己的唯一例項。   3、單例類必須給

    Java模式(Singleton)以及實現

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

    python模式實現方法

    1.方法1,程式執行過程中,某個類物件只有1個,該類物件的例項物件可以有無數個,根絕這點,讓類物件持有一個例項化物件,重寫類物件的__new__方法,始終返回持有的這個例項化物件,即可實現單例模式。 class Person1: _single = None

    c#模式實現方式

        //單例模式一,本模式具有多執行緒不安全性,可通過多執行緒鎖來實現功能     public class Class1     {         //(1)將建構函式定義為private         private Class1()         {  

    模式6實現及利弊分析

    [TOC] # 單例模式6種實現及利弊分析 單例模式三要素 - **私有的構造方法;** - **指向自己例項的私有靜態引用;** - **以自己例項為返回值的靜態的公有方法** ## **1.餓漢式** ```java public class Singleton { private

    Java模式實現方法

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

    java 模式實現方式

    1.懶漢式public class Singleton { private static Singleton instance = null; // 私有化構造方法 private Singleton() { } public static Singleton

    java 模式寫法

    一、懶漢式 public class Singleton{ private static Singleton instance = null; private Singleton(){} public static Singleton newInstance(){