정의

  • 어플리케이션에서 유일하게 존재하는 객체
  • 싱글톤을 이용한 클래스는 new를 이용한 객체를 생성하지 못하고 클래스안의 getInstance() 메소드를 이용하여 객체를 가져온다.(명명규칙)
  • java의 calendar = getInstance해도 새로운 객체를 만들어준다 고로 싱글톤이라할 수 없다
public static Calendar getInstance()
{
    Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
    cal.sharedZone = true;
    return cal;
}
private static Calendar createCalendar(TimeZone zone, Locale aLocale)
{
   Calendar cal = null;
   String caltype = aLocale.getUnicodeLocaleType("ca");
    if (caltype == null) {
        // Calendar type is not specified.
        // If the specified locale is a Thai locale,
        // returns a BuddhistCalendar instance.
        if ("th".equals(aLocale.getLanguage())
                && ("TH".equals(aLocale.getCountry()))) {
            cal = new BuddhistCalendar(zone, aLocale);
        } else {
            cal = new GregorianCalendar(zone, aLocale);
        }
    } else if (caltype.equals("japanese")) {
        cal = new JapaneseImperialCalendar(zone, aLocale);
    } else if (caltype.equals("buddhist")) {
        cal = new BuddhistCalendar(zone, aLocale);
    } else {
        // Unsupported calendar type.
        // Use Gregorian calendar as a fallback.
        cal = new GregorianCalendar(zone, aLocale);
    }
 return cal;
}

적용되는 곳

  • 스레드 풀
  • 캐시
  • 사용자 설정
  • 등등등…

싱글톤의 생성 방법

/* private생성자와 정적 변수를 이용하여 싱글톤을 만드는 방법*/
public class Singleton{
  private static Singleton uniqueInstance;
  private Singleton(){}
  public static Singleton getInstance(){
    if(uniqueInstance == null) uniqueInstance = new Singleton();
    return uniqueInstance;
  }
}

발생하는 문제점

  • 멀티 스레딩에서 최초에 객체가 하나이상 생성될 위험이 있다.

해결 방안 1

  • 동기화(synchronized)를 이용한다.
public class Singleton{
  private static Singleton uniqueInstance;
  private Singleton(){}
  public static synchronized Singleton getInstance(){
    if(uniqueInstance == null) uniqueInstance = new Singleton();
    return uniqueInstance;
  }
}

싱글톤을 위한 동기화의 문제점

  • 동기화는 최초 객체 생성시 한번만 필요한데 그 이후 필요치 않은 동기화로 인해 속도 저하가 발생할 수 있다.
  • 속도에 영향이 없다면 그냥 사용해도 무방하다.

해결 방안 2

  • 객체를 지연생성하지 않고 처음부터 만들어버린다.
public class Singleton{
  private static Singleton uniqueInstance = new Singleton();
  private Singleton(){}
  public static Singleton getInstance(){
    return uniqueInstance;
  }
}

객체를 처음부터 만들때의 문제점

  • 언제 사용할지 모르는 객체를 미리 만들어 둠으로서 자원을 소모
  • 자원 소모가 크지 않다면 이렇게 해도 무방하다.

해결 방안 3

  • DCL(Double-Checking Locking)을 사용한다
public class Singleton{
  private volatile static Singleton uniqueInstance;
  private Singleton(){}
  public static Singleton getInstance(){
    if(uniqueInstance == null) {
      synchronized(Singleton.class){
        if(uniqueInstance == null) {
          uniqueInstance = new Singleton();
        }
      }
    }
    return uniqueInstance;
  }
}

DCL의 문제점

  • 자바 1.4 이하의 버전에서는 사용할 수 없다.

책에 나온 문제점