싱글톤이란 무엇입니까?
싱글톤은 클래스에 적용할 수 있는 가장 간단한 디자인 패턴 중 하나입니다. 사람들은 때때로 "이 클래스는 싱글톤입니다"라고 말합니다. 이는 이 클래스가 싱글톤 디자인 패턴을 구현한다는 의미입니다. 때로는 하나의 객체만 생성할 수 있는 클래스를 작성해야 하는 경우도 있습니다. 예를 들어, 데이터베이스 로깅 또는 연결을 담당하는 클래스입니다. 싱글톤 디자인 패턴은 이러한 작업을 수행하는 방법을 설명합니다. 싱글톤은 다음 두 가지 작업을 수행하는 디자인 패턴입니다.-
클래스가 클래스의 인스턴스를 하나만 갖도록 보장합니다.
-
이 클래스의 인스턴스에 대한 전역 액세스 지점을 제공합니다.
-
개인 생성자. 클래스 자체 외부에서 클래스 객체를 생성하는 기능을 제한합니다.
-
클래스의 인스턴스를 반환하는 공용 정적 메서드입니다. 이 방법을 이라고 합니다
getInstance
. 이는 클래스 인스턴스에 대한 전역 액세스 지점입니다.
구현 옵션
싱글톤 디자인 패턴은 다양한 방식으로 사용됩니다. 각 옵션은 나름대로 좋고 나쁩니다. 항상 그렇듯이 여기에는 이상이 없지만 이를 위해 노력해야 합니다. 하지만 먼저 무엇이 좋고 무엇이 나쁜지 정의하고, 어떤 측정 기준이 디자인 패턴 구현 평가에 영향을 미치는지 살펴보겠습니다. 긍정적인 것부터 시작해보자. 구현에 흥미와 매력을 부여하는 기준은 다음과 같습니다.-
지연 초기화: 애플리케이션이 필요할 때 정확하게 실행되는 동안 클래스가 로드되는 경우입니다.
-
코드의 단순성과 투명성: 물론 지표는 주관적이지만 중요합니다.
-
스레드 안전성: 다중 스레드 환경에서 올바르게 작동합니다.
-
다중 스레드 환경의 고성능: 리소스를 공유할 때 스레드가 서로를 최소한으로 차단하거나 전혀 차단하지 않습니다.
-
지연되지 않은 초기화: 필요 여부에 관계없이 애플리케이션이 시작될 때 클래스가 로드되는 경우(역설적이지만 IT 세계에서는 게으른 것이 더 좋습니다)
-
코드가 복잡하고 가독성이 좋지 않습니다. 측정항목도 주관적입니다. 피가 눈에서 나온다면 구현은 그저 그렇습니다.
-
스레드 안전성이 부족합니다. 즉, "스레드 위험"입니다. 다중 스레드 환경에서 잘못된 작동이 발생합니다.
-
다중 스레드 환경의 성능 저하: 스레드는 항상 서로를 차단하거나 리소스를 공유할 때 자주 차단합니다.
암호
이제 다양한 구현 옵션을 고려하여 장단점을 나열할 준비가 되었습니다.간단한 솔루션
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
가장 간단한 구현. 장점:
-
코드의 단순성과 투명성
-
스레드 안전성
-
멀티스레드 환경에서 뛰어난 성능
- 게으른 초기화가 아닙니다.
지연 초기화
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
장점:
-
지연된 초기화.
-
스레드로부터 안전하지 않음
동기화된 접근자
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
장점:
-
지연된 초기화.
-
스레드 안전성
-
멀티스레드 환경에서 성능 저하
getInstance
동기화되어 한 번에 하나씩만 입력할 수 있습니다. 실제로 전체 메소드를 동기화할 필요는 없고 새 클래스 객체를 초기화하는 부분만 동기화하면 됩니다. synchronized
그러나 새 객체를 생성하는 부분을 블록으로 간단히 감쌀 수는 없습니다 . 이는 스레드 안전성을 제공하지 않습니다. 조금 더 복잡합니다. 올바른 동기화 방법은 다음과 같습니다.
이중 확인 잠금
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
장점:
-
지연된 초기화.
-
스레드 안전성
-
멀티스레드 환경에서 뛰어난 성능
-
1.5 미만의 Java 버전에서는 지원되지 않습니다(휘발성 키워드는 버전 1.5에서 수정되었습니다).
INSTANCE
이어야 합니다 . 오늘 논의할 마지막 구현은 입니다 . final
volatile
Class Holder Singleton
클래스 보유자 싱글톤
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}
장점:
-
지연된 초기화.
-
스레드 안전성.
-
멀티스레드 환경에서 높은 성능을 발휘합니다.
-
Singleton
올바른 작동을 위해서는 클래스 객체가 오류 없이 초기화되도록 보장해야 합니다 . 그렇지 않으면 첫 번째 메서드 호출이getInstance
오류로 종료되고ExceptionInInitializerError
이후의 모든 호출은 실패하게 됩니다NoClassDefFoundError
.
구현 | 지연 초기화 | 스레드 안전성 | 멀티스레딩 속도 | 언제 사용하나요? |
---|---|---|---|---|
간단한 솔루션 | - | + | 빠른 | 절대. 또는 지연 초기화가 중요하지 않은 경우. 하지만 결코 나아지지는 않습니다. |
지연 초기화 | + | - | 해당 없음 | 멀티스레딩이 필요하지 않을 때 항상 |
동기화된 접근자 | + | + | 느리게 | 절대. 또는 멀티스레딩 작업 속도가 중요하지 않은 경우. 하지만 결코 나아질 수는 없어 |
이중 확인 잠금 | + | + | 빠른 | 싱글톤을 생성할 때 예외를 처리해야 하는 드문 경우입니다. (Classholder Singleton이 적용되지 않는 경우) |
클래스 보유자 싱글톤 | + | + | 빠른 | 멀티스레딩이 필요할 때마다 항상 문제 없이 싱글톤 클래스 객체가 생성된다는 보장이 있습니다. |
싱글턴 패턴의 장점과 단점
일반적으로 싱글톤은 예상되는 작업을 정확하게 수행합니다.-
클래스가 클래스의 인스턴스를 하나만 갖도록 보장합니다.
-
이 클래스의 인스턴스에 대한 전역 액세스 지점을 제공합니다.
-
싱글톤은 SRP(단일 책임 원칙)를 위반합니다. 싱글톤 클래스는 즉각적인 책임 외에도 복사본 수를 제어합니다.
-
싱글톤에 대한 일반 클래스나 메서드의 종속성은 클래스의 공개 계약에 표시되지 않습니다.
-
전역 변수가 잘못되었습니다. 싱글톤은 결국 하나의 거대한 전역 변수로 변합니다.
-
싱글톤이 있으면 일반적으로 애플리케이션의 테스트 용이성과 특히 싱글톤을 사용하는 클래스가 줄어듭니다.
GO TO FULL VERSION