728x90

객체에서 단 한개만 만들고 싶을 때, 그리고 단 한개인걸 보장하고 싶을 때 쓰는 패턴이다.


가장 많이 쓰이는건 비즈니스 로직 클래스들이나 UI클래스들 처럼 반드시 단 한개로 쓰고싶을 때 사용한다.

이벤트 테이블이나 핸들러 등의 클래스들도 핸들러 들도 싱글톤 패턴을 많이 사용한다.


가장 기본적인 형태는 아래와 같다.


public class Singleton {
private static Singleton instance = new Singleton();

private Singleton() {
}

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

eager singleton으로 가장 간단한 형태이다.

멀티 스레드로 동작하는 환경이 아니면서 클래스 로더의 부담이 없을 때 사용한다.

다만 예외처리를 할 수 없다.

예외 처리가 필요하다면 조금더 다른 형태를 사용해야한다.


public class Singleton {
private static Singleton instance;

static {
instance = new Singleton();
}

private Singleton() {
}

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

static block singleton으로 위의 형태에서 예외처리만 가능해진 형태이다.

예외처리를 하고싶다면 static 블록에서 처리해주면된다.

eager이나 static block의 경우 클래스가 로딩될때 인스턴스가 로딩되므로 여러 데이터를 처리할때 부담된다.

클래스 로더의 부담을 덜고싶다면 인스턴스가 생성될때만 즉시 하는게 좋다.

즉 늦게 만드는 다른 singleton이 필요하다.


public class Singleton {
private static Singleton instance;

private Singleton() {
}

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

lazy singleton으로 위의 형태에서 클래스 로딩시가 아닌 인스턴스 호출시에 사용하는 패턴이다.

클래스로더의 부담을 덜면서 인스턴스 호출시에만 생성되므로 큰 프로그램 돌릴때 유리하다.

하지만 이정도로 커진 프로그램이라면 멀티스레딩 환경일 확률이높다. eager과 static block과 lazy모두 스레드에서 안전하지 않다.


이제 스레드 세이프한 싱글턴을 만들 때가 됬다.


public class Singleton {
private static Singleton instance;

private Singleton() {
}

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

thread safe singleton으로 synchronized에 의해서 동기화가 적용된다.

하지만 이 모델은 높은 확률로 최악의 병목을 보여주게된다.

만약 10개의 쓰레드에서 getInstance에서 동시에 접근하면 정말 느긋하게 처리하게 될것이다.


public class Singleton {
private Singleton() {
}

private static class SingletonInstance {
private static final Singleton instance = new Singleton();
}

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

initialization on demand holder idiom singleton은 위의 모든 방법을 극복하기위해서 만들어진 singleton 기법이다.

이름이 왜 저모양이냐면 개발한 사람이 이름을 저렇게 붙혀서 그렇다.

이 방식은 자바의 생성 특성을 이용해서 lazy하면서 sync하게 만들 수 있다.

먼저 이너 클래스 SingletonInstance는 Singleton의 getInstance에 접근할때 생성된다. 따라서 lazy하게 생성가능,

내부변수 Singleton은 final이면서 static이니까 무조건 1개인게 보장된다. 따라서 sync하게 사용할 수 있다.




+ Recent posts