Singleton Pattern
: 어떠한 클래스(객체)가 유일하게 1개만 존재해야 할때 사용하는 패턴
즉, 어떤 클래스가 최초 한번만 메모리를 할당하고(Static) 그 메모리에 객체를 만들어 사용하는 디자인 패턴
- 싱글톤으로 생성된 객체는 무조건 한번 생성으로 전역성을 띄기에 다른 객체와 공유가 용이
- 객체 생성을 제활용 할 수 있어 불필요한 메모리 낭비를 방지한다.
- Spring에서 Bean은 기본적으로 Singleton으로 관리를한다.
- 현실세계에서 프린터, 개발에서는 TCP Socket connet등에 자주 사용한다.
문제점
율적이다
- 싱글톤으로 만든 객체의 역할이 복잡해지면 해당 싱글톤 객체를 사용하는 다른 객체간의 결함도가 높아진다.
즉, OCP(Open-Close Principle)에 위반된다.
- 싱글톤 객체를 수정할 경우 싱글톤 객체를 사용하는 곳에서 사이드 이팩트 발생 확률이 존재한다.
- 멀티 쓰래드환경에서 동기화 처리 문제가 일어날 수 있다.
Singleton 구현 방법
Reference: https://elfinlas.github.io/2019/09/23/java-singleton/
static block
public class ExampleClass {
//Instance
private static ExampleClass instance;
//private construct
private ExampleClass() {}
static {
try { instance = new ExampleClass();}
catch(Exception e) { throw new RuntimeException("Create instace fail. error msg = " + e.getMessage() ); }
}
public static ExampleClass getInstance() {
return instance;
}
}
- static 블럭을 사용힐 경우 클래스가 로딩될 때 한번만 실행을 하게 되는 특성을 사용한 방법
- 인스턴스가 사용되는 시점이 아닌 클래스 로딩 시점에 실행이 된다.
lazy init
static 방법을 개선하여 클래스 로딩 시점이 아닌 인스턴스가 필요하여 요청할 때 생성되는 형태로 작성 ```java public class ExampleClass { //Instance private static ExampleClass instance;
//private construct
private ExampleClass() {}
public static ExampleClass getInstance() {
if (instance == null) { instance = new ExampleClass();}
return instance;
} } ``` - 멀티 쓰레드 환경에서 취약 - 쓰레드가 동시에 getInstance() 메서드를 호출하게 되면 인스턴스가 두 번 생성되는 문제가 발생한다.
Thread safe + lazy
public class ExampleClass {
//Instance
private static ExampleClass instance;
//private construct
private ExampleClass() {}
public static synchronized ExampleClass getInstance() {
if (instance == null) { instance = new ExampleClass();}
return instance;
}
}
- synchronized 키워드를 통해쓰레드에서 동시 접근에 대한 문제를 해결했다.
- synchronized 키워드는 성능 저하를 발생시킨다.
Holder
현제 JAVA Singleton 생성에서 사용하는 대표적인 방법이다. ```java public class ExampleClass {
//private construct
private ExampleClass() {}
private static class InnerInstanceClazz() {
private static final ExampleClass instance = new ExampleClass();
}
public static ExampleClass getInstance() {
return InnerInstanceClazz.instance;
} ``` - JVM의 클래스 로더 메커니즘과 클래스의 로드 시점을 이용하여 내부 클래스를 통해 생성 시킴으로써 쓰레드 간의 동기화 문제를 해결한다.
Reference
- https://elfinlas.github.io/2019/09/23/java-singleton/