접근 제어자 : - private, + public, * protected, ~ defalut
C, C++과 달리 전역변수가 없는 Java.
유일한 인스턴스를 만들고 어디서든 참조해 사용할 수 있게 만든다.
기본 싱글톤
- 인스턴스가 처음 요청될 때 생성.
- 구현은 간단하지만 멀티스레드 환경에서 문제 발생할 수 있음
public class LazyInitialization {
private static LazyInitialization instance; // 유일 객체
private LazyInitialization(){}
// 기본 생성자는 public 이기 때문에 private로 명시
// 이는 외부에서 new 키워드를 통해 이 클래스의 인스턴스를 생성하지 못하도록 막습니다.
public static LazyInitialization getInstance() {
// 유일 객체에 접근 방법. LazyInitialization 클래스의 인스턴스를 반환합니다.
if (instance == null) {
instance = new LazyInitialization();
}
return instance;
}
}
멀티스레드 안전 싱글톤
- 멀티스레드 환경에서 안전하게 만드는 방법
- 성능이 떨어질 수 있음
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance; //유일 객체
private ThreadSafeSingleton(){}
// 기본 생성자는 public이므로 private키워드로 명시
// 이는 외부에서 new 키워드를 통해 이 클래스의 인스턴스를 생성하지 못하도록 막습니다.
public static synchronized ThreadSafeSingleton getInstance() {
// 유일 객체에 접근 방법. ThreadSafeSingleton 클래스의 인스턴스를 반환합니다.
// synchronized 키워드를 사용하여 멀티스레드 환경에서 스레드 안전성을 보장합니다.
if (instance == null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
}
이중 체크 싱글톤
- volatile 키워드 사용
- 성능과 스레드 안전성 둘 다 고려한 방법
public class DoubleCheckedLocking {
private static volatile DoubleCheckedLocking instance; // 유일 객체
// volatile은 여러 스레드가 이 변수를 올바르게 읽고 쓸 수 있도록 보장합니다.
private DoubleCheckedLocking(){}
// 기본 생성자는 public이므로 private 키워드를 사용해 명시
// 이는 외부에서 new 키워드를 통해 이 클래스의 인스턴스를 생성하지 못하도록 막습니다.
public static DoubleCheckedLocking getInstance() {
// 유일 객체에 접근 방법. DoubleCheckedLocking 클래스의 인스턴스를 반환합니다.
if (instance == null) {
// 첫번째 null 체크
synchronized (DoubleCheckedLocking.class) {
// synchronized 블록은 Singleton 클래스의 인스턴스 생성이
// 멀티스레드 환경에서도 안전하게 이루어지도록 합니다.
if (instance == null) {
// 두 번째 null 체크: 이중 체크 잠금(Double-Checked Locking) 방식입니다.
// 첫 번째 널 체크 후 다른 스레드가 instance를 초기화하는 경우 방지,
instance = new DoubleCheckedLocking();
}
}
}
return instance;
}
}