티스토리 뷰
싱글톤 (Singleton) 패턴이란?
생성자를 통해 클래스가 여러번 호출이 되어도 하나의 인스턴스를 계속 재활용 하는 방식이다.
싱글톤 사용 이유와 언제 사용하는가?
프로그램 전반에서 하나의 인스턴스로만 사용하는 경우에 사용한다. 예를 들어 DB 커낵션 풀이나 로그 설정 등이 있을 수 있다.
싱글톤 패턴
싱글톤은 여러가지 방법으로 접근할 수 있다. 모든 접근 방법은 다음과 같은 공통 사항을 따른다
- 다른 클래스에서 생성자를 직접 호출하지 못하도록 private constructor를 사용한다.
- private static 의 변수를 사용하여 생성된 인스턴스를 전역에서 사용하도록 한다.
- public static을 사용해서 제어된 방식으로 인스턴스를 얻을 수 있도록 한다.
1. Eager initialization
Eager 단어 의미 그대로 열렬한 방법이다. getInstance 메소드 호출로 인스턴스를 생성하는 것이 아니라 클래스가 로드되는 시점에 인스턴스가 생성된다. 마치 너무 열정적이여서 준비를 미리미리 해놓는 느낌이다. 사용하지 않는데 메모리를 선점하기 때문에 성능에 좋지 않다. 또한 exception을 관리할 수 있는 옵션을 제공하지 않는다.
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance(){
return instance;
}
}
2. Static block initializtion
Eager 방법과 비슷하지만 예외를 처리하는 방법이다.
public class StaticBlockSingleton {
private static StaticBlockSingleton instance;
private StaticBlockSingleton() {}
static {
try{
instance = new StaticBlockSingleton();
} catch (Exception e){
throw new RuntimeException("Exception occurred in creating singleton instance");
}
}
public static StaticBlockSingleton getInstance() {
return instance;
}
}
3. Lazy initializtion
public 메소드에서 인스턴스 생성을 하는데 제약을 두는 방법이다. static 을 통해 변수만 생성한 후에 getInstance를 호출할때 인스턴스를 생성한다. 만약 인스턴스가 있다면 기존의 인스턴스를 활용한다.
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null){
instance = new LazySingleton();
}
return instance;
}
}
하지만 동시에 A, B 쓰레드가 if (instance == null) 에 진입했다면 문제가 될 수 있다. 두개의 쓰레드는 각자 다른 인스턴스를 생성하기 때문에 멀티 쓰레드 환경에서는 문제를 유발하는 방법이다.
4. Thread Safe Singleton
Lazy 방식에서 서로 다른 쓰레드가 동시접근 했을 때의 단점을 보완한 방법이다. getInstance 메소드 호출시 synchronized를 사용하는 방법이다. synchronized는 하나의 쓰레드만 메소드에 접근할 수 있게한다.
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton() {}
public static synchronized ThreadSafeSingleton getInstance() {
if (instance == null){
instance = new ThreadSafeSingleton();
}
return instance;
}
}
하지만 synchronized는 여러 쓰레드가 메소드에 접근할 때 한개의 쓰레드 외에 다른 쓰레드가 접근이 불가능하므로 대기 시간이 발생한다. 따라서 성능 저하를 초래할 수 있다. Double-checked locking 기법을 사용하면 이러한 성능 저하를 막을 수 있다.
public static ThreadSafeSingleton getInstanceUsingDoubleLocking() {
if (instance == null) {
synchronized (ThreadSafeSingleton.class) {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
}
}
return instance;
}
5. Bill Pugh Singleton (Lazy Holder) - 권장되는 방법
클래스 안에 내부 클래스를 두는 형태로 클래스를 초기화할때 쓰레드 세이프한 특징을 이용한 방법이다.
외부 클래스인 Singleton 을 로드할때 내부 글래서 SingletonHolder는 로드 되지 않는다.
getInstance 로 SingletonHolder를 호출하면 클래스가 로드되면서 final로 지정하여 값이 재할당 되지 않도록 한다.
public class Singleton {
private Singleton() {}
private static class SingletonHodler {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHodler.INSTANCE;
}
}
참고 글
'Programming > Java' 카테고리의 다른 글
[Java] SSE(Server-Sent-Event) 구현하기 (0) | 2024.01.01 |
---|---|
[SpringBoot] AOP를 활용하여 컨트롤러 메소드 단위 IP 제약 (0) | 2023.09.11 |
[Springboot] @ControllerAdvice 이용하여 NoHandlerFoundException처리 + thymeleaf (0) | 2023.09.08 |
[Mybatis] foreach를 사용하여 update 하기 (0) | 2023.08.28 |
[java] 싱글톤 기초 패턴 (0) | 2022.07.10 |
- Total
- Today
- Yesterday
- 분산시스템
- 그리디
- Python
- 프로그래머스
- linux
- lightsail
- 백준
- llm
- springboot
- 다이나믹프로그래밍
- 딥러닝
- synflooding
- LangChain
- t-test
- t검정
- 코딩테스트
- 리눅스
- Ai
- FastAPI
- 자료구조
- java
- 정보보안
- 카카오페이
- 카카오페이면접후기
- 보안
- 보안기사
- 파이썬
- 시간초과
- 우선순위큐
- 정보보안기사
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |