* Singleton Pattern (싱글턴 패턴)
-
싱글턴 패턴은 해당 클래스의 인스턴스가 오직 하나만 만들어진다.
-
어디서나 그 인스턴스에 접근할 수 있도록 한다.
-
클래스에서 자신의 단 하나뿐인 인스턴스를 관리하도록 만들면 된다.
* 용도
- 스레드 풀 , 캐시 , 대화상자 , 사용자 설정 , 커넥션 풀 , 디바이스 드라이버 등 객체가 전체 프로그램에서 오직 하나만 생성되어야 하는 경우
* 전역 변수로 static으로 선언해서 사용하면 되지 않을까?
-
만약 전역 변수로 객체를 생성한다면 어플리케이션이 실행 될 때 객체가 생성 될 것이다. 그러나 그 객체가 자원을 많이 차지 한다면 사용도 하기 전에, 괜한 자원만 차지하게 된다.
* 고전적인 싱글턴 패턴 구현법
아래 방식의 코드는 다중 스레드를 사용할 때 각 스레드가 getInstance 메소드를 동시에 호출하면(거의 비슷하게) 두 개의 객체가 생겨버릴지도 모른다. 지금은 간단하지만 나중에 복잡한 인스턴스가 두 개 이상 존재할 경우 어떤 결과를 초래하게 될 지 알 수 없다.
public class Singleton { // private으로 Sinleton클래스의 유일한 인스턴스를 // 저장하기 위한 정적 변수를 선언 private static Singleton uniqueInstance; // 생성자를 private로 선언했기 때문에 Singleton에서만 // 클래스를 만들 수 있다. private Singleton() { } // 클래스의 인스턴스를 만들어서 리턴해 준다. public static Singleton getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; } }
* 멀티스레딩 문제 해결 방법
getInstance() 를 동기화시키기만 하면 멀티스레딩과 관련된 문제가 간단하게 해결된다. 그러나 동기화를 하게 되면 불필요한 오버헤드가 생기기 때문에 속도 문제가 발생할 수 있다. (대부분 그렇다.)
public class Singleton { private static Singleton uniqueInstance; // 기타 인스턴스 변수 private Singleton() { } // synchronized 키워드만 추가하면 두 스레드가 // 이 메소드를 동시에 실행시키는 일은 일어나지 않게 된다. public static synchronized Singleton getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; } // 기타 메소드 }
* 더 효율적인 방법
1. getInstance()의 속도가 그리 중요하지 않다면 그냥 내버려 둔다.
- 메소드를 동기화하면 성능이 100배 정도 저하된다는 것을 기억하자.
- 만약 getInstance() 가 어플리케이션에서 병목으로 작용한다면 다른 방법을 생각해봐야 한다.
2. 인스턴스를 필요할 때 생성하지 말고, 처음부터 만들어 버린다.
이런 접근법을 사용하면 클래스가 로딩될 때 JVM에서 Singleton의 유일한 인스턴스를 생성해 준다.
public class Singleton { private static Singleton uniqueInstance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return uniqueInstance; } }
3. DCL(Double-Checking Locking)을 써서 getInstance()에서 동기화되는 부분을 줄인다.
DCL(Double-Checking Locking)을 사용하면, 일단 인스턴스가 생성되어 있는지 확인한 다음, 생성되어 있지 않았을 때만 동기화를 할 수 있다. volatile 키워드를 사용하여 멀티스레딩을 쓰더라도 uniqueInstance 변수가 Singleton 인스턴스로 초기화 되는 과정이 올바르게 할 수 있다. DCL은 자바 1.4 이하 버전에서 사용할 수 없다.
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; } }
'Java' 카테고리의 다른 글
자바빈(javaBean) 의 값을 보다 쉽게 확인하는 util (0) | 2014.04.27 |
---|---|
Java 날짜 연산 팁!! (0) | 2014.03.15 |
주어진 문자열이 다수의 문자열 집합에 속하는지 검증하는 유틸성 클래스 (0) | 2013.12.13 |
아규먼트(argument) 와 파라미터(parameter) 의 차이 (0) | 2013.10.17 |
Java에서 Linux Shell 명령어 실행하기 (0) | 2013.08.26 |