單例模式的五種實現與比較

一、懶漢式實現單例模式讀取配置文件

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.util.Properties;  
  4.   
  5. //懶漢式  
  6. public class Singleton1 {  
  7.     /** 
  8.      * 定義一個類變量用來存放創建好的類實例 
  9.      */  
  10.     private static  Singleton1 uniqueInstance = null;  
  11.     /** 
  12.      * 用來存放配置文件的參數paramA的值 
  13.      */  
  14.     private String paramA;  
  15.     /** 
  16.      * 用來存放配置文件的參數paramB的值 
  17.      */  
  18.     private String paramB;  
  19.       
  20.     //返回參數paramA的值  
  21.     public String getParamA() {  
  22.         return paramA;  
  23.     }  
  24.     //返回參數paramB的值  
  25.     public String getParamB() {  
  26.         return paramB;  
  27.     }  
  28.     /** 
  29.      * 私有化構造方法 
  30.      */  
  31.     private Singleton1(){  
  32.         readConfig();  
  33.     }  
  34.     /** 
  35.      * 讀取配置文件,把讀取的信息設置到屬性上 
  36.      */  
  37.     private void readConfig() {  
  38.         Properties p = new Properties();  
  39.         InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");  
  40.         try {  
  41.             p.load(in);  
  42.         } catch (IOException e) {  
  43.             // TODO Auto-generated catch block  
  44.             e.printStackTrace();  
  45.         }  
  46.         this.paramA = p.getProperty("paramA");  
  47.         this.paramB = p.getProperty("paramB");  
  48.     }  
  49.     /** 
  50.      * 定義一個方法來爲客戶端提供Singleton1類實例 
  51.      * @return 一個Singleton1類實例 
  52.      */  
  53.     public static Singleton1 getSingleton1Instance(){  
  54.         if(uniqueInstance == null){  
  55.             uniqueInstance = new Singleton1();  
  56.             return uniqueInstance;  
  57.         }  
  58.           
  59.         return uniqueInstance;  
  60.     }  
  61. }  

二、餓漢式實現單例模式讀取配置文件

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.util.Properties;  
  4.   
  5. //餓漢式  
  6. public class Singleton2 {  
  7.     /** 
  8.      * 定義一個類變量用來存放創建好的類實例 
  9.      */  
  10.     private static  Singleton2 uniqueInstance = new Singleton2();  
  11.     /** 
  12.      * 用來存放配置文件的參數paramA的值 
  13.      */  
  14.     private String paramA;  
  15.     /** 
  16.      * 用來存放配置文件的參數paramB的值 
  17.      */  
  18.     private String paramB;  
  19.       
  20.     //返回參數paramA的值  
  21.     public String getParamA() {  
  22.         return paramA;  
  23.     }  
  24.     //返回參數paramB的值  
  25.     public String getParamB() {  
  26.         return paramB;  
  27.     }  
  28.     /** 
  29.      * 私有化構造方法 
  30.      */  
  31.     private Singleton2(){  
  32.         readConfig();  
  33.     }  
  34.     /** 
  35.      * 定義一個方法來爲客戶端提供Singleton2類實例 
  36.      * @return 一個Singleton2類實例 
  37.      */  
  38.     public static Singleton2 getSingleton2Instance(){  
  39.         return uniqueInstance;  
  40.     }  
  41.     /** 
  42.      * 讀取配置文件,把讀取的信息設置到屬性上 
  43.      */  
  44.     private void readConfig() {  
  45.         Properties p = new Properties();  
  46.         InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");  
  47.         try {  
  48.             p.load(in);  
  49.         } catch (IOException e) {  
  50.             // TODO Auto-generated catch block  
  51.             e.printStackTrace();  
  52.         }  
  53.         this.paramA = p.getProperty("paramA");  
  54.         this.paramB = p.getProperty("paramB");  
  55.     }  
  56. }  

三、緩存實現單例模式

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5. import java.util.Properties;  
  6.   
  7. //用緩存來實現單例模式  
  8. public class Singleton3 {  
  9.     /** 
  10.      * 定義一個默認的key值 
  11.      */  
  12.     private final static String DEFAULT_KEY ="one";  
  13.     /** 
  14.      * 緩存實例的容器 
  15.      */  
  16.     private static  Map<String,Object> map = new HashMap<String,Object>();  
  17.       
  18.     /** 
  19.      * 用來存放配置文件的參數paramA的值 
  20.      */  
  21.     private String paramA;  
  22.     /** 
  23.      * 用來存放配置文件的參數paramB的值 
  24.      */  
  25.     private String paramB;  
  26.       
  27.     //返回參數paramA的值  
  28.     public String getParamA() {  
  29.         return paramA;  
  30.     }  
  31.     //返回參數paramB的值  
  32.     public String getParamB() {  
  33.         return paramB;  
  34.     }  
  35.     /** 
  36.      * 構造方法私有化 
  37.      */  
  38.     private Singleton3(){  
  39.         readConfig();  
  40.     }  
  41.     /** 
  42.      * 定義一個方法來爲客戶端提供Singleton3類實例 
  43.      * @return 一個Singleton3類實例 
  44.      */  
  45.     public static Singleton3 getSingleton3Instance(){  
  46.         Singleton3 instance = (Singleton3) map.get("one");  
  47.         if(instance==null){  
  48.             instance = new Singleton3();  
  49.             map.put(DEFAULT_KEY, instance);  
  50.         }  
  51.         return instance;  
  52.     }  
  53.     /** 
  54.      * 讀取配置文件,把讀取的信息設置到屬性上 
  55.      */  
  56.     private void readConfig() {  
  57.         Properties p = new Properties();  
  58.         InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");  
  59.         try {  
  60.             p.load(in);  
  61.         } catch (IOException e) {  
  62.             // TODO Auto-generated catch block  
  63.             e.printStackTrace();  
  64.         }  
  65.         this.paramA = p.getProperty("paramA");  
  66.         this.paramB = p.getProperty("paramB");  
  67.     }  
  68. }  
四、通過雙重檢查加鎖的方式實現單例模式

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.util.Properties;  
  4. //通過雙重檢查加鎖的方式實現單例模式  
  5. public class Singleton4 {  
  6.     /** 
  7.      * 用來存放配置文件的參數paramA的值 
  8.      */  
  9.     private String paramA;  
  10.     /** 
  11.      * 用來存放配置文件的參數paramB的值 
  12.      */  
  13.     private String paramB;  
  14.       
  15.     //返回參數paramA的值  
  16.     public String getParamA() {  
  17.         return paramA;  
  18.     }  
  19.     //返回參數paramB的值  
  20.     public String getParamB() {  
  21.         return paramB;  
  22.     }  
  23.     /** 
  24.      * 構造方法私有化 
  25.      */  
  26.     private Singleton4(){  
  27.         readConfig();  
  28.     }  
  29.     /** 
  30.      * 保存實例變量添加volatile關鍵詞修飾 
  31.      */  
  32.     private volatile static Singleton4 uniqueInstance = null;  
  33.     /** 
  34.      * 讀取配置文件,把讀取的信息設置到屬性上 
  35.      */  
  36.     private void readConfig() {  
  37.         Properties p = new Properties();  
  38.         InputStream in = Singleton4.class.getResourceAsStream("AppConfig.properties");  
  39.         try {  
  40.             p.load(in);  
  41.         } catch (IOException e) {  
  42.             // TODO Auto-generated catch block  
  43.             e.printStackTrace();  
  44.         }  
  45.         this.paramA = p.getProperty("paramA");  
  46.         this.paramB = p.getProperty("paramB");  
  47.     }  
  48.     /** 
  49.      * 定義一個方法來爲客戶端提供Singleton4類實例 
  50.      * @return 一個Singleton4類實例 
  51.      */  
  52.     public static Singleton4 getSingleton4Instance(){  
  53.         //先檢查實例是否存在,如果不存在才進入下面的同步快  
  54.         if(uniqueInstance == null){  
  55.             //同步塊,線程安全的創建實例對象  
  56.             synchronized (Singleton4.class){  
  57.                 uniqueInstance = new Singleton4();  
  58.                 return uniqueInstance;  
  59.             }  
  60.         }  
  61.           
  62.         return uniqueInstance;  
  63.     }  
  64. }     

五、通過JVM保證線程安全的方式實現單例模式(高人的方法)

[java] view plain copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.util.Properties;  
  4. //通過JVM保證線程安全性  
  5. public class Singleton5 {  
  6.       
  7.     private String paramA;  
  8.       
  9.     private String paramB;  
  10.   
  11.     public String getParamA() {  
  12.         return paramA;  
  13.     }  
  14.   
  15.     public String getParamB() {  
  16.         return paramB;  
  17.     }  
  18.       
  19.     private static class SingletonHolder{  
  20.         private static Singleton5 instance = new Singleton5();  
  21.     }  
  22.       
  23.     public static Singleton5 getSingleton5Instance(){  
  24.         return SingletonHolder.instance;  
  25.     }  
  26.       
  27.     private Singleton5(){  
  28.         readConfig();  
  29.     }  
  30.       
  31.     private void readConfig() {  
  32.         Properties p = new Properties();  
  33.         InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");  
  34.         try {  
  35.             p.load(in);  
  36.         } catch (IOException e) {  
  37.             // TODO Auto-generated catch block  
  38.             e.printStackTrace();  
  39.         }  
  40.         this.paramA = p.getProperty("paramA");  
  41.         this.paramB = p.getProperty("paramB");  
  42.     }  
  43. }  

下面是本文所使用的配置文件:

AppConfig.properties

內容爲:

paramA = AAAAAA
paramB = BBBBBB


五種方法的比較

第一種方法,是以時間換空間,實現了延遲加載,但線程不安全;

第二種方法,是以空間換時間,沒有實現延遲加載,線程安全;

第三種方法,與第一種方法相比,由於是通過緩存,所以效率大大提高,但同樣是線程不安全的;

第四種方法,實現了延遲加載和線程安全,使用雙重檢查加鎖的方法,使得性能不會有太大的影響,但會屏蔽掉虛擬機中一些必要的代碼優化,所以運行效率並不是很高;

第五種方法:高人的方法,這個解決方案被稱爲Lazy initialization holder class模式,這個模式綜合使用了java的類級內部類和多線程缺省同步鎖的知識,很巧妙的同時實現了延遲加載和線程安全。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章