일반적인 싱글톤 패턴은 멀티스레드 환경에서 단일 인스턴스 생성을 보장하지 못한다. 그래서 멀티스레드에서도 사용가능한 방법이다.
스레드 안전하지 않음
public class Singleton {
private final static Singleton INSTANCE = null;
private Singleton() {
// ...
}
private static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
스레드 문제는 해결해주지만, 이 방법의 단점은 사용할 시점에 생성하는 것(lazy loading,lazy construct─늦은 로딩/늦은 생성)이 아니라 Singleton 이라는 클래스가 로딩될 그 시점에 생성된다는 것이다.
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {
// ...
}
private static Singleton getInstance() {
return INSTANCE;
}
}
스레드 문제는 해결해주지만, 위 방법은 getInstance 메서드 전체를 동기화 잠금을 걸기 때문에 성능이 좋지 않다.
public class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {
// ...
}
// synchronized 키워드 추가
private static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
방법2과 다를 바 없다(...) syncronized 를 안에다 하나 밖에다 하나 .. 뭐 거기서 거기
public class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {
// ...
}
// synchronized 키워드를 안쪽에 추가
private static Singleton getInstance() {
synchronized (Singleton.class) {
if(INSTANCE == null) {
INSTANCE = new Singleton();
}
}
return INSTANCE;
}
}
아래의 방법은 static inner class를 이용하여 동기화 문제를 피하고, 필요한 시점에 인스턴스를 생성한다. 원리는 static의 로딩시점을 이용한 것이다. 모든 자바 버전에서도 잘 돌아간다.
public class Singleton {
private final static class SingletonHoler {
public final static Singleton INSTANCE = new Singleton();
}
private Singleton() {
System.out.println("싱글톤 생성!");
}
private static Singleton getInstance() {
return SingletonHoler.INSTANCE;
}
}