'singletonPattern'에 해당되는 글 1건

  1. 2019.04.27 singleton-pattern

singleton-pattern

JAVA/Design patten 2019. 4. 27. 17:47 |

Singleton-pattern

단 하나의 인스턴스를 생성해 사용하는 패턴

 

why?

고정된 메모리 영역을 얻으면서 한번의 new로 인스턴스를 사용하기 때문에 메모리 낭비를 방지할 수 있음

또한,싱글톤으로 만들어진 클래스의 인스턴스는 전역 인스턴스이기 때문에 다른 클래스의 인스턴스들이 데이터를 공유하기 쉽다

커넥션 풀, 스레드 풀 등 객체생성시 싱글톤 사용

 

1. eager initialization  (이른 초기화)

싱글톤 패턴중에 가장 기본적인 싱글톤 패턴이다

이른 초기화 방식은 싱글톤 객체를 미리 생성해 놓은 방식이다.

전역변수로 instance 변수 생성하고 private static 선언하여 직접 바로 접근할 수 없도록 합니다.

생성자에도 private 접근 제어 키워드를 붙여 다른 클래스에서 new EagerInitialization() 방식으로 새로운 인스턴스 생성하는 것을 방지한다.

오로지 정적메소드인 getInstance() 메서드를 통해 인스턴스를 접근하도록 하여 동일한 인스턴스를 사용하는 기본 싱글톤원칙을 지키게한다.

/**
 *
 * 가장 기본적인 singleton pattern
 * new EagerInitialization () 될때 어떠한 예외처리도 할 수 없다는것이 단점
 */
public class EagerInitialzation {

	//private 으로 선언하여 외부에서 접근 불가
	//static 으로 인스턴스화 없이 사용 가능함
	private static EagerInitialzation instance = new EagerInitialzation();

	// private 으로 생성자 선언하여 new 키워드로 인스턴스 생성 불가능
	private EagerInitialzation(){
		System.out.println("call EagerInitialzation constructor");
	}

	//instance의 직접 접근도 불가능하고 생성자도 불가능하기 때문에 getInstance() 로 만 인스턴스 가질수있음
	public static EagerInitialzation getInstance(){
		return instance;
	}
}

 

2. Static block initialization

이른초기화와 같은 방식으로 초기에 인스턴스 만들어놓지만 static 구문에 로직을 추가하여 수행하는 패턴이다

logic을 담을수 있기 때문에 복잡한 초기변수 셋팅이나 예외처리를 위한 구문을 담을수 있다.

 

/**
 *
 * Static block initialization
 * logic을 담을수 있기 때문에 복잡한 초기변수 셋팅이나 위와 같이 에러처리를 위한 구문을 담을수 있다.
 */
public class StaticBlockInitialization {

	private static StaticBlockInitialization instance;

	private StaticBlockInitialization (){ }
	// static 으로 정의하여 초기화 블럭을 이용하여 클래스가 로딩될때 최초 한번 실행하게 됨.
	static {
		try {
			System.out.println("instance create...");
			instance = new StaticBlockInitialization();
		}catch (Exception e){
			throw new RuntimeException("Exception creating StaticBlockinitalation instace.....");
		}
	}

	public static StaticBlockInitialization getInstance(){
		return instance;
	}
}

 

 

3. Lazy initialization (게으른 초기화)

게으른 초기화는 인스턴스를 사용하는 시점에 사용한다. 

instance 변수를 private static 으로 전역변수로 만들고 생성자도 private 로 선언하여 외부에서 생성 못하게 한다.

오직 getIntance() 메소드를 통해 인스턴스 생성 및 호출되는데, 최초 호출일 경우 인스턴스 객체 생성한다.

만약 멀티 쓰레드를 방식에서 getInstance() 를 두번 호출하게 되면 인스턴스가 두번 생성될 수 있는 문제점이 있다.

 

/**
 * Eager initialization,static block 방법은 클래스가 로딩될때 인스턴스 생성하기 때문에 프로그램이 커지만 부담이 될수 있다.
 * Lazy 초기화는 인스턴스를 사용하는 시점에 사용한다.
 * 만약 멀티 쓰레드 방식이라서 getinstance()를 두번 호출하게 되면 두번 생성 될수 있다.
 */
public class LazyInitialization {

	private static LazyInitialization instance;
	private LazyInitialization(){};

	public static LazyInitialization getInstance(){
		if (instance == null)
			instance = new LazyInitialization();
		return instance;
	}
}

 

4.Thread Safe Lazy initialization(스레드 안전한 늦은 초기화)

Lazy 싱글톤 방식에서 thread safe 문제가 있어 이를 보완하기 위해 멀티쓰레드에서 스레드들이 동시 접근하는

동시성을 synchronized 키워드를 이용해 해결하는 방식이다.

 

/**
 * sychronized 블록으로 인해, 수 많은 쓰레드 들이 인스턴스 호출하게 되면 높은 cost 비용으로 인해
 *  프로그램 전반에 성능저하가 일어난다.
 *
 */
public class ThreadSafeInitialization {
	private static ThreadSafeInitialization instance;
	private ThreadSafeInitialization(){}

	//여러 thread 들이 동시에 접근해서 인스턴스를 생성시키는 위험은 없어짐!
	public static synchronized ThreadSafeInitialization getInstance(){
		if (instance==null)
			instance = new ThreadSafeInitialization();
		return instance;
	}
}

synchronized 키워드를 사용할 경우 자바 내부적으로 해당 영역이나 메서드를 lock,unlock 처리하기때문에 많은 cost가 발생함

=> 성능저하됨!

 

4-1. Thread Safe Initialization + double - checked locking 기법 싱글톤 패턴

위에 Thread safe initialization 에서 synchronized 처리된 메서드가 성능저하가 발생되어 완화하기 위해

Double checked locking 기법을 사용한다.

instance가 null 일 경우에 synchronized 블럭에 접근하고 한번더 instance의 null 유무를 체크한다.

if문 두번다 null 일 경우 new를 통해 인스턴스화시킨다.

그후 instance 가 null이 아니기때문에 synchronized 블록을 타지 않는다.

Double checked locking 으로 성능저하 줄임

 

public class ThreadSafeLazyInitialization {
 
    private static ThreadSafeLazyInitialization instance;
 
    private ThreadSafeLazyInitialization(){}
     
    public static ThreadSafeLazyInitialization getInstance(){
        //Double-checked locking
        if(instance == null){
            synchronized (ThreadSafeLazyInitialization.class) {
                if(instance == null)
                    instance = new ThreadSafeLazyInitialization();
            }
 
        }
        return instance;
    }
}

 

'JAVA > Design patten' 카테고리의 다른 글

factory method pattern  (0) 2019.04.27
Decorator Pattern (데코레이터 패턴)  (0) 2015.09.03
옵저버 패턴의 정의  (0) 2015.08.21
Posted by 양승아
: