=> 클래스의 인스턴스를 하나만 생성하고, 어디서든 그 인스턴스를 참조할 수 있도록 하는 패턴
=> 생성자가 여러 번 호출해도 실제로 생성되는 객체는 하나
1. Eager initialization
public class EagerSingleton{
private static EagerSignleton instance=new EagerSingleton();
private EagerSingleton(){
}
public static EagerSingleton getInstance(){
return instance;
}
}
장점 : 속도가 빠름
단점 : 클라이언트에서 사용하지 않더라도 인스턴스가 항상 생성됨(메모리 낭비), 예외처리 할 수 있는 방법이 없음
2. Static block initialization
public class StaticBlockSingleton {
private static StaticBlockSingleton instance;
private StaticBlockSingleton(){}
static{
try{
instance = new StaticBlockSingleton();
}catch (Exception e){
throw new RuntimeException("싱글톤 객체 생성 오류");
}
}
public static StaticBlockSingleton getInstance(){
return instance;
}
}
장점 : initialization과 유사하지만 인스턴스가 static block 안에서 생성돼서 예외 처리 가능
단점 : 여전히 처음에 인스턴스가 생성됨
3. Lazy initialization
public class LazyInitializationSingleton {
private static LazyInitializationSingleton instance;
private LazyInitializationSingleton(){}
public static LazyInitializationSingleton getInstance(){
if (Objects.isNull(instance)) {
instance = new LazyInitializationSingleton();
}
return instance;
}
}
장점 : getInstance() 호출 이외에 인스턴스를 생성하지 않음, Eager initialization의 단점을 보완
단점 : Non Thread Safe
4. Thread safe initialization
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton(){}
public static synchronized ThreadSafeSingleton getInstance(){
if (instance==null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
}
장점 : Thread Safe ( Synchronized 이용해서 하나의 스레드만 접근 가능하도록 설정 )
단점 : 성능이 비효율적
5. Double-Checked Locking
public class DoubleCheckedLockingSingleton {
private static DoubleCheckedLockingSingleton instance=null;
private DoubleCheckedLockingSingleton(){}
public static DoubleCheckedLockingSingleton getInstance(){
if (Objects.isNull(instance)) {
synchronized (DoubleCheckedLockingSingleton.class){
instance = new DoubleCheckedLockingSingleton();
}
}
return instance;
}
}
Null 체크를 synchronized 블록 밖에서 한번, 안에서 한번 총 두 번 실행 밖에서 하는 체크는 인스턴스가 있는 경우 빠르게 리턴하기 위해서 안쪽에서 하는 체크는 인스턴스가 생성되지 않는 경우 하나의 인스턴스만 생성하기 위해서
6. Bill Pugh Solution
public class BillPughSingleton {
private static BillPughSingleton instance=null;
private static class SingletonHelper{
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
public static BillPughSingleton getInstance(){
return SingletonHelper.INSTANCE;
}
}
Double Checked 에 비해 구현이 간단
Lazy Loading이 가능, Thread Safe
=> 모든 메소드가 static인 클래스를 지칭
=> inner static class를 뜻하기도 함
1. Static Variable
2. Static Method
3. Static Class
우아한Tech의 테코톡(크로플님의 싱글턴과 정적클래스)를 참조하였습니다.