設計模式之單例模式深究

爲何使用單例模式?
        我認爲是因爲某些對象的建立比較耗時,對內存的消耗又比較大回收成本太高,這時候若是容許
不斷的建立對象代價勢必過高,若是使用單例讓內存中始終保持一個對象那麼顯然更划算java

反例:ide

    ①. 同時執行1000個線程測試測試

public class Singleton3 {
	private static  Singleton3 INSTANCE;
	private Singleton3(){}
	public static Singleton3 getInstance(){
			if(INSTANCE == null){
				newInstance();
			}
		
		return INSTANCE;
	}
	private static void newInstance(){
		INSTANCE = new Singleton3();
	}


//test

public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
		final CyclicBarrier cb = new CyclicBarrier(1000);
		for(int i = 0; i <1000;i++){
			Thread t = new Thread(new Runnable() {
				
				@Override
				public void run() {
					try {
						cb.await();
                    } catch (Exception e) {
	                    e.printStackTrace();
                    }
					System.out.println(Singleton3.getInstance().hashCode());
				}
			});
			t.start();
		}
	}

 測試結果經過notepad++計數發現有幾個不一致的發現有不一致的hashcode線程

11009893 --不一致
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
31038155
26417394  --不一致
31038155
31038155
31038155
...
省略

②.加鎖的方式:code

public static Singleton3 getInstance(){
		if (INSTANCE == null) {
			try {
				// 模擬一個耗時操做
	            Thread.sleep(3000);
	        } catch (InterruptedException e) {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        }
			synchronized (Singleton3.class) {
				newInstance();
			}
		}
		return INSTANCE;
	}


//結果顯而易見

18000767
10320474
9913454
2027657
10262576
15487566
15487566
28392674
15487566
6268557
6268557
25920236
....略

③.雙重檢查加鎖(即作兩次判斷):這種方式雖然可行,可是使用鎖畢竟會加劇程序不建議使用對象

if (INSTANCE == null) {
			try {
				// 模擬一個耗時操做
	            Thread.sleep(3000);
	        } catch (InterruptedException e) {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        }
			synchronized (Singleton3.class) {
				newInstance();
			}
		}
		return INSTANCE;
	}
	private static void newInstance(){
		if(INSTANCE == null){
			INSTANCE = new Singleton3();
		}
	}

------------------------------------------內存

使用以下幾種方式:get

①.靜態塊的方式:只會第一次建立對象的方式進來hash

private static  final Singleton2 INSTANCE;
	static{
		System.out.println("static.");
		INSTANCE = new Singleton2();
	}
	private Singleton2(){}
	public static Singleton2 getInstance(){
		return INSTANCE;
	}

②.相似於①it

private static  final Singleton INSTANCE = new Singleton();
	private Singleton(){
		System.out.println("construct.");
	}
	public static Singleton getInstance(){
		return INSTANCE;
	}

③.枚舉的方式(必須是單元素):

public enum Singleton4 {
	INSTANCE;
	public int get(){
		try {
			// 模擬耗時
	        Thread.sleep(1000);
        } catch (InterruptedException e) {
	        e.printStackTrace();
        }
		return Singleton4.class.hashCode();
	}
}

④.靜態內部類:略

------------------------------------

相關文章
相關標籤/搜索