본문으로 바로가기
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


싱글톤 패턴이란

인스턴스가 사용될 때에 똑같은 인스턴스를 여러개 만들어 내는 것이 하니라 한 개의 인스턴스를 사용하는 것이다.

다시 말해 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴이다.



사용할까 ?

한가지 예를 들자면 서버에서 xml정보를 읽어와서 프로그램 설정을 한다고 가정할 때, 서버에 접속할 때마다 xml의 값을 파싱해서 읽을 필요는 없다.

맨 처음 xml에서 값을 읽어와 인스턴스에 저장해놓고 저장해 놓은 인스턴스를 활용하면 된다.


Eager initialization

가장 기본적인 SingleTon Pattern  예제이다. 

singleton에서 중요한 것을 정리하면


  • private 멤버 변수로 자기 자신의 클래스의 인스턴스를 가진다.
  • private 생성자를 지정하여 외부에서는 인스턴스를 생성하지 못한다.
  • getInstance() method에 static을 이용하여 객체를 가져올 수 있다.


public class SingleTonPattern {
    private static SingleTonPattern instance = new SingleTonPattern();
    
    private SingleTonPattern() {
        System.out.println("call SingletonPattern Constructor");
    }
    
    public static SingleTonPattern getInstance() {
        return instance;
    }
    
    public void print() {
        System.out.println("singletonpattern_print");
    }
}


위의 패턴은 작은 프로그램일 때는 문제가 없지만 프로그램의 크기가 커져서 수 많은 클래스에서 위와 같은 singleton pattern을 사용한다고 가정한다면

new SingleTonPattern()으로 인해 클래스가 load되는 시점에 인스턴스를 생성시키는데 부담스러울 수가 있다. 또한 이 소스는 클래스가 인스턴스화 하는 시점에 어떠한 에러처리도 할 수 없다.




public class SingleTonPattern {
    private static SingleTonPattern instance;
    
    static {
        try {
            instance = new SingleTonPattern();
        } catch (Exception e) {
            throw new RuntimeException("Exception creating instance.");
        }
    }
    
    private SingleTonPattern() {
        System.out.println("call SingletonPattern Constructor");
    }
    
    public static SingleTonPattern getInstance() {
        return instance;
    }
    
    public void print() {
        System.out.println("singletonpattern_print");
    }
}


static 초기화 블록을 이용하여 클래스가 로딩 될 때 최초 한번 실행하게 된다. 또한 복잡한 변수 셋팅과 에러처리를 위한 구문을 담을 수 있다.

첫 번째 예제보다는 좋아보이지만 인스턴스가 사용되는 시점에 생성되지는 않는다.




lazy initialization 


public class SingleTonPattern { private static SingleTonPattern instance; private SingleTonPattern() { System.out.println("call SingletonPattern Constructor"); } public static SingleTonPattern getInstance() { if(instance == null) { instance = new SingleTonPattern(); } return instance; } public void print() { System.out.println("singletonpattern_print"); } }


new SingleTonPattern은 static를 이용한 getInstance안에 사용되었다. if문을 이용하 instance가 null일 경우에만 객체를 생성한다. 클래스를 로드할 때가 아닌 getInstance()를 호출하는 사용시점에 객체를 인스턴스화 시키기 때문에 부담이 줄게 된다. 그러나 만약 프로그램이 multi thread방식이라면  위와 같은 singleton pattern은 안전하지 않다. 동일 시점에서 getInstance()를 호출하면 인스턴스가 두 번 생길 위험이 있다.




Synchronized Singleton


public class SingleTonPattern {
    private static SingleTonPattern instance;
    
    private SingleTonPattern() {
        System.out.println("call SingletonPattern Constructor");
    }
    
    public static synchronized SingleTonPattern getInstance() {
        if(instance == null) {
            instance = new SingleTonPattern();
        }
        return instance;
    }
    
    public void print() {
        System.out.println("singletonpattern_print");
    }
}


multi thread일 경우 문제를 해결하기 위해 getInstance() 메소드에 synchronized를 선언하였다. 하지만 위 코드에 여러 쓰레드가 동시에 접근할 경우 한 번에 한 쓰레드만 getInstance()메소드를 사용할 수 있으므로 다른 쓰레드들은 instance를 사용중인 쓰레드가 작업이 끝날 때까지 기다려야한다.