단일 모드 7

3428 단어 Singleton
package com.sohu.zookeeper;
//첫 번째(게으름뱅이, 라인이 안전하지 않음):
public class Singleton {
	private static Singleton instance;

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

//이런 쓰기 방법은 lazy loading이 뚜렷하지만 치명적인 것은 다선정이 정상적으로 작동하지 못한다는 것이다.두 번째(게으름뱅이, 라인 안전):
public class Singleton {
	private static Singleton instance;

	public static synchronized Singleton getInstance() {
		if (instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

//이런 맞춤법은 다중 라인에서 좋은 작업을 할 수 있을 뿐만 아니라 좋은 lazy loading을 갖추고 있는 것처럼 보이지만, 유감스럽게도 효율이 낮고 99퍼센트의 경우 동기화할 필요가 없다.세 번째(아사자):
public class Singleton {
	private static Singleton instance = new Singleton();

	private Singleton() {
	};

	public static Singleton getInstance() {
		return instance;
	}
}

//이런 방식은classloder 메커니즘을 바탕으로 다중 라인의 동기화 문제를 피하지만 instance는 클래스를 불러올 때 실례화됩니다.
//클래스를 불러오는 원인은 여러 가지가 있지만 단일 모드에서 getInstance 방법을 사용하는 경우가 대부분이고,
//그러나 다른 방식(또는 다른 정적 방법)이 클래스를 불러오는 것을 확정할 수 없고,
//이때 instance를 초기화하는 것은 분명히 lazy loading의 효과에 이르지 못했다. 네 번째(굶주린 사람, 변종):
public class Singleton {
	private Singleton instance = null;
	static {
		instance = new Singleton();
	}

	public static Singleton getInstance() {
		return this.instance;
	}
} 

//표면적으로 보면 차이가 매우 커 보이지만 사실 세 번째 방식은 차이가 많지 않다. 모두 클래스 초기화 즉 실례화 instance이다.다섯 번째(정적 내부 클래스):
public class Singleton {
	private static class SingletonHolder {
		private static final Singleton INSTANCE = new Singleton();
	}

	public static final Singleton getInstance() {
		return SingletonHolder.INSTANCE;
	}
}

//이런 방식 역시classloder의 메커니즘을 이용하여 instance를 초기화할 때 하나의 라인만 있음을 확보한다.
//그것은 세 번째 방식과 네 번째 방식과 다른 것은 (미세한 차이): 세 번째 방식과 네 번째 방식은 싱레톤류가 불러오기만 하면
//그러면 instance가 실례화됩니다(lazy에 도달하지 못함
//loading 효과), 이런 방식은 Singleton 클래스가 불러옵니다. instance가 반드시 초기화되는 것은 아닙니다.
//SingletonHolder 클래스가 주동적으로 사용되지 않았기 때문에 getInstance 방법을 호출할 때만 SingletonHolder 클래스를 불러오는 것을 표시합니다.
//instance를 인스턴스화합니다.만약에 실례화 instance가 자원을 많이 소모한다면 로드를 늦추고 싶습니다. 다른 한편,
//Singleton 클래스가 불러올 때 실례화되기를 원하지 않습니다. 왜냐하면 Singleton 클래스가 다른 곳에서 주동적으로 사용되어 불러올 수 있기 때문입니다.
//그렇다면 이럴 때 instance를 실례화하는 것은 분명 적합하지 않다.이럴 때 이런 방식은 세 번째와 네 번째 방식에 비해 매우 합리적으로 보인다.
//여섯 번째(열거):
public enum Singleton {
	INSTANCE;
	public void whateverMethod() {
	}
}

//이런 방식은 Effective Java 저자 Josh Bloch
//제창하는 방식은 다선정 동기화 문제를 피할 수 있을 뿐만 아니라 반서열화로 새로운 대상을 재창설하는 것을 방지할 수 있어 강한 장벽이라고 할 수 있다.
//하지만 개인적으로는 1.5에 엔음의 특성을 넣었기 때문에 이런 식으로 쓰면 낯설다고 생각합니다. 실제 업무에서 이렇게 쓴 사람을 본 적이 거의 없습니다.
//일곱 번째 (이중 검사 자물쇠):
public class Singleton {
	private volatile static Singleton singleton;

	public static Singleton getSingleton() {
		if (singleton == null) {
			synchronized (Singleton.class) {
				if (singleton == null) {
					singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
}

좋은 웹페이지 즐겨찾기