設計模式(二)單例模式(創建型)

使用場景:

       一個類只能創建一個實例對象。如讀取服務器配置文件的類,由單個實例對象直接讀取。


實現流程:

      (1)、定義一個私有變量;

      (2)、將構造函數私有化;

      (3)、提供一個獲取實例的公用方法;


     下面列出幾種常見的實現模式,僅供參考:

      餓漢式單例:在類創建的時候就初始化實例對象,每次調用的時候都是獲取同一對象實例,是線程安全的。

      實現類:

public class HungrySingleton {
	
	private static HungrySingleton instance = new HungrySingleton();
	
	private HungrySingleton(){};
	
	public static HungrySingleton getInstance(){
		return instance;
	}

}

      測試類:

public class HungrySingletonTest {
	
	private class MyThread extends Thread{
		
		@Override  
		public void run(){
			System.out.println(HungrySingleton.getInstance().hashCode());
		}
		
	}
	
	public static void main(String[] args) {  
		MyThread[] mts = new MyThread[10];  
        for(int i = 0 ; i < mts.length ; i++){  
            mts[i] = new HungrySingletonTest().new MyThread();  
        }  
          
        for (int j = 0; j < mts.length; j++) {  
            mts[j].start();  
        }  
	}

}


      測試結果:


        從測試結果可以看出,該方式是線程安全的。


        普通懶漢式單例:創建類的時候不實例化對象,在調用獲取實例方法的時候才創建對象。是線程不安全的。

        實現類:

public class LazySingleton {
	
	private static LazySingleton instance = null;
	
	private LazySingleton(){};
	
	public static LazySingleton getInstance(){
		if(instance == null){
			instance = new LazySingleton();
		}
		return instance;
	}

}

         測試類:

public class LazySingletonTest {
	
    private class MyThread extends Thread{
		
		@Override  
		public void run(){
			System.out.println(LazySingleton.getInstance().hashCode());
		}
		
	}
    
    public static void main(String[] args) { 
		MyThread[] mts = new MyThread[10];  
        for(int i = 0 ; i < mts.length ; i++){  
            mts[i] = new LazySingletonTest().new MyThread();  
        }  
          
        for (int j = 0; j < mts.length; j++) {  
            mts[j].start();  
        }  
	}

}

        測試結果:


     從測試結果可以看出,該方式是線程不安全的。


      對線程不安全的懶漢式單例模式,有多種的解決方案。簡單的如:在獲取實例的公共方法里加上同步標識符synchronized。這樣的話可以保證在多線程的環境下獲取的實例是唯一的,但也相應地影響了效率。這裏列舉一種常規的解決方案——Double Check Locking雙檢查鎖機制。


     雙檢查鎖機制(DCL)

     實現類:

public class DclSingleton {
	
	//使用volatile保證線程間可見性
	private static volatile DclSingleton instance = null;
	
	private DclSingleton(){};
	
	public static  DclSingleton getInstance(){
		if(instance == null){
			synchronized(DclSingleton.class){
				//二次檢查
				if(instance == null){
					instance = new DclSingleton();
				}
			}
		}
		return instance;
	}

}


       測試結果

    從測試結果可以看出,該方式是線程安全的,且將同步的範圍限制到了最小。是推薦的一種單例實現方式。


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