JAVA, Singleton 싱글톤

한 어플리케이션에서 단 하나의 객체만을 만들고 그것을 보장할 필요로 할 때가 있다. 이때 만들어진 유일무이한 객체를 싱글톤이라고 한다. 싱글톤을 타겟으로 하는 클래스의 생성 방식은 다음과 같다.

public class PersonDao {
	private static PersonDao instance;
    
	private PersonDao(){	}
    
	public static PersonDao getInstance() {
		if(instance ==null) {
			instance = new PersonDao();
            System.out.println("PersonDao 초기화");
        }
		return instance;		
	}
}

메인 스레드에서 해당 객체를 getInstance() 메서드를 통해 싱글톤을 호출하는 방법은 아래와 같다.

public class MemberMain {
	public static void main(String[] args) {
//		PersonDao pDao1 = new PersonDao(); // private 이기 때문에 메인 스레드에서 해당 클래스를 찾을 수 없음. 컴파일 오류 발생. 
	
		PersonDao dao2 = PersonDao.getInstance(); // 출력 : PersonDao 초기화
		System.out.println("dao2 :"+dao2); // dao2 :PersonDao@3830f1c0

		PersonDao dao3 = PersonDao.getInstance();
		System.out.println("dao3 :"+dao3); // dao3 :PersonDao@3830f1c0

		PersonDao dao4 = PersonDao.getInstance();
		System.out.println("dao4 :"+dao4);// dao4 :PersonDao@3830f1c0
 
	}
}

싱글톤 생성에 있어서 중요한 부분은 static(정적 맴버)이다. static이 있어야만 메소드 영역에 해당 값이 저장되고, 어플리케이션 내에서 유일함을 보장받으며, 어플리케이션이 끝날 때 까지 사용될 수 있다.
하지만 앞서 예제의 싱글톤은 애플리케이션 내에서 유일함을 보장할 수 없다. 특정 스레드에 메소드를 통해 호출되었고, 이는 특정 메서드에 종속되어 작동할 위험을 내포한다.
메서드가 아닌 클래스를 통해 객체를 호출하면 이러한 위험을 우회할 수 있다. 클래스를 로딩 할 때 싱글톤을 호출하면, 스레드로부터 무관(thread-safe)하게 작동한다. 아래의 예제는 메서드가 아닌 클래스에서 객체를 초기화함을 볼 수 있다. 참고로 lazy를 붙인 이유는, 어플리케이션이 생성될 때 해당 객체를 생성하는 것이 아니라, 그것이 필요할 때까지 객체 생성을 미룬다는 의미로 이해할 수 있다.

public class PersonDao {
	
	private PersonDao(){}

	public static PersonDao getInstance() {
		return LazyHolder.INSTANCE; 
	}
	
	private static class LazyHolder {
		private static final PersonDao INSTANCE = new PersonDao(); 
	}
}

참고 :

좋은 웹페이지 즐겨찾기