一、懶漢式實現單例模式讀取配置文件
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
- //懶漢式
- public class Singleton1 {
- /**
- * 定義一個類變量用來存放創建好的類實例
- */
- private static Singleton1 uniqueInstance = null;
- /**
- * 用來存放配置文件的參數paramA的值
- */
- private String paramA;
- /**
- * 用來存放配置文件的參數paramB的值
- */
- private String paramB;
- //返回參數paramA的值
- public String getParamA() {
- return paramA;
- }
- //返回參數paramB的值
- public String getParamB() {
- return paramB;
- }
- /**
- * 私有化構造方法
- */
- private Singleton1(){
- readConfig();
- }
- /**
- * 讀取配置文件,把讀取的信息設置到屬性上
- */
- private void readConfig() {
- Properties p = new Properties();
- InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");
- try {
- p.load(in);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- this.paramA = p.getProperty("paramA");
- this.paramB = p.getProperty("paramB");
- }
- /**
- * 定義一個方法來爲客戶端提供Singleton1類實例
- * @return 一個Singleton1類實例
- */
- public static Singleton1 getSingleton1Instance(){
- if(uniqueInstance == null){
- uniqueInstance = new Singleton1();
- return uniqueInstance;
- }
- return uniqueInstance;
- }
- }
二、餓漢式實現單例模式讀取配置文件
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
- //餓漢式
- public class Singleton2 {
- /**
- * 定義一個類變量用來存放創建好的類實例
- */
- private static Singleton2 uniqueInstance = new Singleton2();
- /**
- * 用來存放配置文件的參數paramA的值
- */
- private String paramA;
- /**
- * 用來存放配置文件的參數paramB的值
- */
- private String paramB;
- //返回參數paramA的值
- public String getParamA() {
- return paramA;
- }
- //返回參數paramB的值
- public String getParamB() {
- return paramB;
- }
- /**
- * 私有化構造方法
- */
- private Singleton2(){
- readConfig();
- }
- /**
- * 定義一個方法來爲客戶端提供Singleton2類實例
- * @return 一個Singleton2類實例
- */
- public static Singleton2 getSingleton2Instance(){
- return uniqueInstance;
- }
- /**
- * 讀取配置文件,把讀取的信息設置到屬性上
- */
- private void readConfig() {
- Properties p = new Properties();
- InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");
- try {
- p.load(in);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- this.paramA = p.getProperty("paramA");
- this.paramB = p.getProperty("paramB");
- }
- }
三、緩存實現單例模式
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Properties;
- //用緩存來實現單例模式
- public class Singleton3 {
- /**
- * 定義一個默認的key值
- */
- private final static String DEFAULT_KEY ="one";
- /**
- * 緩存實例的容器
- */
- private static Map<String,Object> map = new HashMap<String,Object>();
- /**
- * 用來存放配置文件的參數paramA的值
- */
- private String paramA;
- /**
- * 用來存放配置文件的參數paramB的值
- */
- private String paramB;
- //返回參數paramA的值
- public String getParamA() {
- return paramA;
- }
- //返回參數paramB的值
- public String getParamB() {
- return paramB;
- }
- /**
- * 構造方法私有化
- */
- private Singleton3(){
- readConfig();
- }
- /**
- * 定義一個方法來爲客戶端提供Singleton3類實例
- * @return 一個Singleton3類實例
- */
- public static Singleton3 getSingleton3Instance(){
- Singleton3 instance = (Singleton3) map.get("one");
- if(instance==null){
- instance = new Singleton3();
- map.put(DEFAULT_KEY, instance);
- }
- return instance;
- }
- /**
- * 讀取配置文件,把讀取的信息設置到屬性上
- */
- private void readConfig() {
- Properties p = new Properties();
- InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");
- try {
- p.load(in);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- this.paramA = p.getProperty("paramA");
- this.paramB = p.getProperty("paramB");
- }
- }
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
- //通過雙重檢查加鎖的方式實現單例模式
- public class Singleton4 {
- /**
- * 用來存放配置文件的參數paramA的值
- */
- private String paramA;
- /**
- * 用來存放配置文件的參數paramB的值
- */
- private String paramB;
- //返回參數paramA的值
- public String getParamA() {
- return paramA;
- }
- //返回參數paramB的值
- public String getParamB() {
- return paramB;
- }
- /**
- * 構造方法私有化
- */
- private Singleton4(){
- readConfig();
- }
- /**
- * 保存實例變量添加volatile關鍵詞修飾
- */
- private volatile static Singleton4 uniqueInstance = null;
- /**
- * 讀取配置文件,把讀取的信息設置到屬性上
- */
- private void readConfig() {
- Properties p = new Properties();
- InputStream in = Singleton4.class.getResourceAsStream("AppConfig.properties");
- try {
- p.load(in);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- this.paramA = p.getProperty("paramA");
- this.paramB = p.getProperty("paramB");
- }
- /**
- * 定義一個方法來爲客戶端提供Singleton4類實例
- * @return 一個Singleton4類實例
- */
- public static Singleton4 getSingleton4Instance(){
- //先檢查實例是否存在,如果不存在才進入下面的同步快
- if(uniqueInstance == null){
- //同步塊,線程安全的創建實例對象
- synchronized (Singleton4.class){
- uniqueInstance = new Singleton4();
- return uniqueInstance;
- }
- }
- return uniqueInstance;
- }
- }
五、通過JVM保證線程安全的方式實現單例模式(高人的方法)
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
- //通過JVM保證線程安全性
- public class Singleton5 {
- private String paramA;
- private String paramB;
- public String getParamA() {
- return paramA;
- }
- public String getParamB() {
- return paramB;
- }
- private static class SingletonHolder{
- private static Singleton5 instance = new Singleton5();
- }
- public static Singleton5 getSingleton5Instance(){
- return SingletonHolder.instance;
- }
- private Singleton5(){
- readConfig();
- }
- private void readConfig() {
- Properties p = new Properties();
- InputStream in = Singleton1.class.getResourceAsStream("AppConfig.properties");
- try {
- p.load(in);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- this.paramA = p.getProperty("paramA");
- this.paramB = p.getProperty("paramB");
- }
- }
下面是本文所使用的配置文件:
AppConfig.properties
內容爲:
paramA = AAAAAA
paramB = BBBBBB
五種方法的比較
第一種方法,是以時間換空間,實現了延遲加載,但線程不安全;
第二種方法,是以空間換時間,沒有實現延遲加載,線程安全;
第三種方法,與第一種方法相比,由於是通過緩存,所以效率大大提高,但同樣是線程不安全的;
第四種方法,實現了延遲加載和線程安全,使用雙重檢查加鎖的方法,使得性能不會有太大的影響,但會屏蔽掉虛擬機中一些必要的代碼優化,所以運行效率並不是很高;
第五種方法:高人的方法,這個解決方案被稱爲Lazy initialization holder class模式,這個模式綜合使用了java的類級內部類和多線程缺省同步鎖的知識,很巧妙的同時實現了延遲加載和線程安全。