單例模式小記

java中單例模式是一種常見的設計模式,單例模式分爲三種:懶漢式單例、惡漢式單例和登記式單例。java

單例模式有如下特色設計模式

 一、單例只能有一個實例安全

 二、單例必須本身建立本身的惟一實例多線程

 三、單例必須給其餘對象提供惟一實例app

懶漢式單例線程

public class Singleton {
	
	private static Singleton single = new Singleton();
	
	private Singleton(){}//私有化構造器
	
	public static Singleton getInstance() {
		return single;
	}
}

 

餓漢式單例設計

public class Singleton {

        private static Singleton single = null;
	
        private Singleton(){}
	
	public static Singleton getInstance() {
	    if (single == null) {
	        single = new Singleton();
	    }
	    return single;
	}
}

在單線程環境下,上面的惡漢式不存在任何問題,但在多線程環境下,線程A和B,線程A第一次進入判斷single爲null,而後CPU切換到線程B,B判斷single也爲null,此時B線程會執行new Singleton(),而後CPU切回線程A,線程A繼續執行也會new Singleton(),此時就會出現兩個實例,問題就出來了。code

考慮到多線程環境下多線程安全問題,高效的餓漢式修改以下cdn

public class Singleton {

        private static Singleton single = null;
	
        private Singleton(){}
	
	public static Singleton getInstance() {
	    //旨在避免實例化後其它線程在進入這個方法後進入同步代碼塊,提升效率
	    if (single != null) {
                return single;
	    }
    	    synchronized (Singleton.class) {
	        //第一個線程進入同步代碼塊,多個線程等待拿同步代碼塊的鎖,進入同步代碼塊
    		//當第一個線程實例化,離開同步代碼塊後
		//其它等待拿同步所的線程依次進入能夠直接返回實例化對象
        	if (single != null) {
        	    return single;
    		}
    		single = new Singleton();
	    }
	    return single;
	}
}

若是須要進一步提升效率能夠拋棄同步代碼塊使用Lock鎖對象

public class Singleton {

	private static Singleton single = null;
	
	private Singleton(){}
	
	public static Singleton getInstance() {
	        //旨在避免實例化後其它線程在進入這個方法後進入同步代碼塊,提升效率
		if (single != null) {
		    return single;
		}
		ReentrantLock lock = new ReentrantLock(false);
		try {
		    lock.lock();
		    if (single != null) {
			return single;
		    }
		    single = new Singleton();
		} catch (Exception e) {
		    System.err.println(e.getMessage());
		} finally {
		    lock.unlock();
		}
		return single;
	}
}

 

登記式單例

等級是單例這個單例實際上維護的是一組單例類的實例(父類和子類),講這些實例存放在一個Map(登記薄)中,對於已經登記過的實例,則從Map中獲取直接返回,對於沒有登記的,則先登記,再返回。

@SuppressWarnings("unchecked")
public class Singleton {

	@SuppressWarnings("rawtypes")
	private static HashMap map = new HashMap();
	
	private Singleton (){}

	static {
		Singleton single = new Singleton();
		map.put(single.getClass().getName(), single);
	}

	public static Singleton getInstance(String name) {
		if (name == null) {
			name = "Singleton";
		}
		if (map.get(name) == null) {
			try {
				map.put(name, Class.forName(name).newInstance());
			} catch (Exception e) {
				System.out.println("Error happened.");
			}
		}
		return (Singleton) map.get(name);
	}
}

其子類實現

public class SingletonChild extends Singleton {

	private SingletonChild(){}
	
	public static SingletonChild getInstance() {
		return (SingletonChild) Singleton.getInstance("SingletonChild");
	}
}
相關文章
相關標籤/搜索