爲何使用單例模式?
我認爲是因爲某些對象的建立比較耗時,對內存的消耗又比較大回收成本太高,這時候若是容許
不斷的建立對象代價勢必過高,若是使用單例讓內存中始終保持一個對象那麼顯然更划算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(); } }④.靜態內部類:略
------------------------------------