본문 바로가기

개발

[JAVA] 싱글톤 구현 예제



1. 싱글톤 구현

 - Logger 클래스 구현 


public class Logger {


// 싱글톤을 생성하고 저장함

private static final Logger instance = new Logger();

// 다른 사람은 아무도 이 클래스를 생성할 수 없도록 함

private Logger(){}

// 싱글톤 인스턴스 리턴

public static Logger getInstance(){

return instance;

}


// 콘솔에 문자열 로그 출력

public void log(String msg){

System.out.println(System.currentTimeMillis() + ": " + msg);

}

  // main 

public static void main(String[] args) {

Logger.getInstance().log(": 싱글톤 구현");

}


}


 - * 위 예문은 Logger 클래스의 인스턴스가 여러개 생길수가 있음

 


2. 지연 초기화

 - 클래스 생성 시 싱글톤 인스턴스를 무조건 만들어야하 하는 것이 아니므로 getInstance에서 인스턴스가 아직 초기화 전이라면 초기화해서 리턴할 수 있다. (지연 초기화 or 지연 로딩이라고 부름)


 - 지연 초기화 장단점

  -> 구동 시간은 빨라지지만, 인스턴스 액세스시 초기화 시간이 걸림

  -> 싱글톤을 한 번도 액세스 하지 않으면 초기화가 되지 않기 때문에 클래스 호출 시 초기화에 필요한 시간과 자원을 소모함

 -> 자원이 제한된 환경에서는 자원이 부족해서 뒤늦게 인스턴스를 초기화할 때 문제가 생길수 있음. 필요할 때 반드시 만들어져 있어야 하는 에러 로킹 클래스의 경우에는 특히 문제가 될 수 있음

 -> 싱글톤 클래스가 더 복잡해 짐. 특히 멀티 스레드 시스템에서는 더 복잡해 짐


 - 지연 초기화 예제


 public class Logger {


// 싱글톤을 생성하고 저장함

private static Logger instance = null; // final 삭제

// 다른 사람은 아무도 이 클래스를 생성할 수 없도록 함

private Logger(){}

// 싱글톤 인스턴스 리턴

public static Logger getInstance(){

if(instance == null){

instance = new Logger();

}

return instance;

}

// 콘솔에 문자열 로그 출력

public void log(String msg){

System.out.println(System.currentTimeMillis() + ": " + msg);

}

public static void main(String[] args) {

Logger.getInstance().log(": 지연 초기화");

}


}


- * 위 예문은 스레드 안전성 문제가 생길 수 있음

- * 두 스레드에서 getInstance를 동시에 호출하면 각각 인스턴스를 생성하려고 할 것임

- * 다음과 같이 동기화된 메소드로 구현


public synchronized static Logger getInstance(){

if(instance == null){

instance = new Logger();

}

return instance;

}


- * 위 예문은 속도에 영향이 있겠지만 getInstance를 자주 호출하지 않는다면 큰 문제는 되지 않음


- 가장 이상적인 예문


public class Logger {

// 다른 사람은 아무도 이 클래스를 생성할 수 없도록 함

private Logger(){}


// 내부 클래스가 로딩될 때 초기화도 함께 진행됨

// getInstance()에서 참조하기 전까지는 로딩되지 않음

private static class LoggerHolder{

public static final Logger instance = new Logger();

}

public static Logger getInstance(){

return LoggerHolder.instance;

}

// 콘솔에 문자열 로그 출력

public void log(String msg){

System.out.println(System.currentTimeMillis() + ": " + msg);

}

public static void main(String[] args) {

Logger.getInstance().log(": 지연 초기화");

}


}





출처 : http://www.hanbit.co.kr/store/books/look.php?p_code=B9005920688


맨 위로