Singleton

싱글톤 패턴은 애플리케이션 내에서 단 하나의 인스턴스만 생성되어 공유되어야 할 때 사용합니다. 대표적인 예로 로깅(Logger)이나 스프링빈이 있습니다.


Default Singleton (Eager Initialization)

클래스가 로딩될 때 미리 인스턴스를 생성합니다.

  • 장점: 구현이 간단하며 멀티스레드 환경에서도 안전합니다.

  • 단점: 사용하지 않더라도 인스턴스가 생성되어 메모리 낭비가 발생할 수 있습니다.

public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();

    private EagerSingleton() { }

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

Instance Field 방식

클래스 로딩 시점에 인스턴스가 생성되므로 Default 방식과 동일하게 메모리 사용이 불필요할 수 있습니다.

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

    private InstanceFieldSingleton() { }

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

Lazy Loading

클래스가 로딩될 때 인스턴스를 생성하지 않고, 실제로 필요할 때 생성하여 메모리 낭비를 줄입니다.

  • 장점: 실제 사용 시점에 인스턴스를 생성하므로 메모리 효율적입니다.

  • 단점: 멀티스레드 환경에서 동기화(synchronized) 처리가 필요합니다.

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() { }

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

Standard / Joshua 블록 방식

Joshua Bloch가 제안한 방식으로, Bill Pugh의 내부 정적 클래스 방식을 사용합니다. 이 방법은 클래스 로딩 시점과 실제 사용 시점의 장점을 모두 취하며, 멀티스레드 환경에서 안전합니다.

public class StandardSingleton {
    private StandardSingleton() { }

    private static class SingletonHelper {
        private static final StandardSingleton INSTANCE = new StandardSingleton();
    }

    public static StandardSingleton getInstance() {
        return SingletonHelper.INSTANCE;
    }
}
  • Default/Instance Field 방식: 클래스 로딩 시점에 인스턴스가 생성되어 간단하지만, 사용하지 않을 경우에도 인스턴스가 생성됩니다.

  • Lazy Loading 방식: 인스턴스가 실제로 필요할 때 생성하여 메모리를 효율적으로 사용하지만, 동기화 비용이 발생할 수 있습니다.

  • Standard/Joshua 방식: Bill Pugh의 내부 클래스 방식을 활용해 스레드 안전하면서도 지연 초기화를 구현할 수 있습니다.

Last updated