시스템 런타임, 환경 세팅에 대한 정보 등, 인스턴스가 여러개일 때 문제가 생길 수 있는 경우가 있음
인스턴스를 오직 한개만 만들어 제공하는 클래스가 필요

 

싱글톤 패턴이란?

- 인스턴스를 오직 한개만 제공하는 클래스

 

목적

1. 인스턴스를 오직 한개만 생성

2. 하나의 인스턴스에 글로벌하게 접근할 수 있는 방법을 제공

 

사용 예시

-  java.lang.runtime

- 스프링에서 빈의 스코프 중에 하나로 싱글톤 스코프

- 다른 디자인 패턴(빌더, 퍼사드, 추상 팩토리 등) 구현체의 일부로 쓰이기도 함

구현 방법1. private 생성자에 static 메소드

public class Settings {

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

- 위 방법은 멀티쓰레드 환경에서 getInstance 호출하는 시점에 따라 인스턴스가 여러개 생성 될 수 있어서 안전하지 않음
L 두개의 쓰레드가 동시에 if 문 안으로 들어오면 인스턴스가 두개 생김

 

Tip1. 자바의 경우 private 생성자를 만들면 클래스 밖에서는 생성자를 사용할 수 없음

Tip2. 자바의 경우 static 함수를 제공하면 객체를 생성하지 않고 메소드를 사용할 수 있음

 

구현 방법2. 동기화를 사용해 멀티쓰레드 환경에 안전하게 만드는 방법

public class Settings {

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

- sychronized 키워드 사용해서 getInstance에 한번에 하나의 쓰레드만 블록 안으로 접근 하도록 설정

L 단점: getInstance를 사용할때마다 동기화처리하는 작업 때문에 성능에 불이익이 생길 수 있음

 

Tip3. 자바의 경우 sychronized 키워드 사용하면 한번의 하나의 쓰레드만 처리하게 할 수 있음

 

구현 방법3. 이른 초기화 (eager initialization)을 사용하는 방법

public class Settings {

  private static final Settings INSTANCE = new Settings();
  
  private Settings() {}; 
  
  public static Settings getInstance() {
    return INSTANCE;
  }
  
}


- 단점: 인스턴스를 만드는 과정의 비용이 크다면 굳이 사용할 필요가 없는 경우에도 애플리케이션 로딩시 많은 리소스를 많이 사용할 수 있음

 

구현 방법4. 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;
  }
  
}

- 1번보다 효율적인 이유: 멀티쓰레드 환경에서 안전함

- 2번보다 효율적인 이유: getInstance를 사용할때마다 동기화가 걸리지 않음
- 3번보다 효율적인 이유: 실제 instance를 사용할때 생성함
- volatile을 써야해서 자바 1.5이상에서 동작

구현 방법5. static inner 클래스 사용하기

public class Settings {
  
  private Settings() {}; 
  
  private static class SettingsHolder {
    private static final Settings INSTANCE = new Settings();
  }
  
  public static Settings getInstance() {
    return SettingsHolder.INSTANCE;
  }
  
}

특징

- 지연 로딩, 쓰레드 세이프티

+ Recent posts