싱글톤 패턴(Singleton Pattern)
- 인스턴스를 오직 한개만 제공하는 클래스
- 시스템 런타임, 환경 세팅에 대한 정보 등, 인스턴스가 여러개 일 때 문제가 생길 수 있는 경우 사용
naive
public class Settings {
private static Settings instance;
private Settings() {}
public static Settings getInstance() {
if (instance == null) {
instance = new Settings();
}
return instance;
}
}
- naive(단순)하게 고려한 싱글톤 코드
- private 생성자를 통해 new 생성자의 사용을 막음
- public static method를 통해 객체를 생성하게 만듬
- multi thread 환경을 고려하지 못한 싱글톤 코드임
- 서로 다른 두개의 쓰레드가 동시에 if(instance == null)을 확인하고 다음 코드를 실행하면 서로다른 new Settings() 객체를 가지게 됨
synchronized
public class Settings {
private static Settings instance;
private Settings() {}
public static synchronized Settings getInstance() {
if (instance == null) {
instance = new Settings();
}
return instance;
}
}
- synchronized 키워드를 사용하여 멀티 쓰레드 환경에서 안전하게 객체를 생성할 수 있음
- synchronized 키워드는 성능을 저하 시킴
eager initialization
public class Settings {
private static final Settings INSTANCE = new Settings();
private Settings() {}
public static Settings getInstance() {
return INSTANCE;
}
}
- synchronized 성능 저하가 신경쓰이고 객체를 나중에 만들지 않고 객체를 생성하는 비용이 비싸지 않으면 이른 초기화(eager initialization)를 사용하여도 됨
- 이른 초기화 자체가 단점이 될 수 있음 -> 많은 비용을 들여 생성을 했지만 사용하지 않을 경우
double checked locking
public class Settings {
private static volatile Settings instance;
private Settings() {}
public static Settings getInstance() {
if (instance == null) {
synchronized (Settings.class) {
if (instance == null) {
instance = new Settings();
}
}
}
return instance;
}
}
- double checked locking을 사용하여 효율적인 동기화 블럭을 만들 수 있음
- 쓰레드가 동시에 if (instance == null)을 확인하고 다음 코드를 진행하였을 경우에만 synchronized 블록을 실행하기 때문에 모든 메서드에 synchronized가 걸려있을 때 보다 성능 저하가 적음
- instance를 필요로 하는 시점에 만들 수 있음
- 자바 1.5 이상에서 사용 가능한 코드
- 코드가 복잡함
static inner class
public class Settings {
private Settings() {}
private static class SettingsHolder {
private static final Settings INSTANCE = new Settings();
}
public static Settings getInstance() {
return SettingsHolder.INSTANCE;
}
}
- 멀티 쓰레드 환경에서도 안전하고 getInstance() 메서드가 호출이 될 때 SettingsHolder.INSTANCE를 생성하기 때문에 lazy loading이 가능한 코드
실무에서 사용하는 싱글톤 예제
- java.lang.Runtime
- ApplicationContext 내부에서 유일한 객체를 보장함(스프링 빈) -> 엄밀히 말하면 싱글톤 패턴과는 좀다름, 싱글톤 스코프
- 다른 디자인 패턴(빌더, 퍼사드, 추상 팩토리 등) 구현체의 일부로 사용하기도 함