반응형
Notice
Recent Posts
Recent Comments
관리 메뉴

꿈꾸는 사람.

[디자인 패턴][싱글턴 패턴] 안드로이드 6.0 싱글턴 패턴 예제. 본문

IT/Language_Design Patterns

[디자인 패턴][싱글턴 패턴] 안드로이드 6.0 싱글턴 패턴 예제.

현무랑 니니 2016. 1. 12. 18:00
반응형


프로그램을 작성 중 객체를 하나만 써야 하는 경우가 많이 있다.

스레드 풀, 캐시, 사용자 설정과 레지스트리 설정을 처리하는 객체와 그래픽 카드, Wi-Fi나 bluetooth 장치를 위한 디바이스 드라이버와 같은 것들이 대표적인 예이다.


쉬운 접근법은 전역 변수를 사용하는 것이다.

자바의 전역 변수는 기본적으로 객체에 대한 정적 레퍼런스이다.

처음부터 끝까지 인스턴스를 가져야 하고 게으른(lazy) 인스턴스 생성을 할 수 없다.

또한 전역 레퍼런스를 자꾸 만들게 되어 네임스페이스가 지저분해진다.


이럴 때 인스턴스가 하나 뿐인 객체를 만들 수 있는 디자인 패턴이 필요하다.

1. 싱글턴(Singleton) 패턴 개념.

싱글턴 패턴은 해당 클래스의 인스턴스가 하나만 만들어지고, 그 인스턴스에 대한 전역 접근할 수 있게 하는 패턴이다.

1.1 고전적인 싱글턴 패턴(The classic Singleton Pattern)

public class Singleton {

private static Singleton uniqueInstance;

 

// other useful instance variables here

 

private Singleton() {}

 

public static Singleton getInstance() {

if (uniqueInstance == null) {

uniqueInstance = new Singleton();

}

return uniqueInstance;

}

 

// other useful methods here

}



















문제점

- 두 개의 스레드가 getInstance()를 호출할 때 발생하는 문제.

 1번 스레드

 2번 스레드

 uniqueInstance 값

 public static Singleton getInstance() {

 

 null

 

 public static Singleton getInstance() {

 null

  if (uniqueInstance == null) {

 

 null

 

  if (uniqueInstance == null) {

 null

  uniqueInstance = new Singleton();

 

 <object 1>

 

  uniqueInstance = new Singleton();

 <object 2>

  return uniqueInstance;

 

 <object 1>

 

  return uniqueInstance;

 <object 2>

1.2. 멀티태스킹 문제 해결한 싱글턴 패턴(The Singleton Pattern)

1) getInstance()를 동기화시킨다.

getInstance()에 synchronized 키워드만 추가하면 한 스레드가 메소드 사용을 끝내기 전에 다른 스레드가 이 메소드를 동시에 실행할 수 없게 된다.

자바에서 메소드를 동기화하면 성능이 100배 정도 저하된다고 하니 속도가 중요한 경우에는 적합하지 않다.


2) 인스턴스를 필요할 때가 아닌 처음부터 만든다.

애플리케이션이 항상 Singleton의 인스턴스를 만들고 사용할 경우나 생성과 실행에 대한 부하가 문제되지 않으면 처음부터 인스턴스를 만들어도 좋다.

클래스가 로딩될 때 JVM이  Singleton의 유일한 인스턴스를 생성한다.

JVM이 유일한 인스턴스를 생성하기 전에 어떤 스레드도 정적 uniqueInstance 변수에 접근할 수 없다.


3) "DCL (Double-Checking Locking)"을 써서 getInstanc()에서 동기화되는 부분을 줄인다.

인스턴스가 생성되었는지 확인한 후, 생성되지 않았을 때만 동기화를 사용한다.

이 방법은 처음에만 동기화한다.

2. 안드로이드 6.0 Marshmallow의 Singleton Pattern 예제.

2.1. Wi-Fi 장치를 모니터링하는 WifiMonitor

1) WifiMonitor의 클래스 다이어그램이다.

WifiMonitor 클래스는 싱글톤 패턴에 해당하는 WifiMonitorSingleton 서브클래스와 실제 모니터링한 스레스 클래스인 MonitorThread를 가진다.


2) Singleton 패턴을 이용한 인스턴스를 만드는 sequence diagram이다.


▶ 1 ~ 2 단계: WifiMonitorSingleton 서브클래스가 로딩될 때 JVM이 다음 코드로 Singleton의 유일한 인스턴스를 생성하여 준다.

정적 인스턴스로 생성되는 것이 핵심이다.

private static final WifiMonitorSingleton sInstance = new WifiMonitorSingleton();




▶ 3 ~ 6 단계: WifiService 클래스가 WifiServiceImpl() -> WifiStateMachine()를 통하여 WifiMonitor() 생성자를 호출하여 WifiMonitor의 인스턴스를 만든다.

public WifiStateMachine(...) {

    ...

    mWifiMonitor = new WifiMonitor(this, mWifiNative);

    ...







▶ 7 단계: WifiMonitorSingleton 서브클래스가 인터페이스 키에 해당하는 WifiMonitor 값을 관리한다.

관련 내용은 다음 글 [[Android] Wi-Fi 서비스에서 JAVA Hashmap 사용 예.]을 참고하라.


▶ 8 단계: WifiStateMachine가 InitialState 상태에서 CMD_START_SUPPLICANT 이벤트를 받으면 모니터링을 시자하려 startMonitoring()호출한다.


▶ 9 ~ 10 단계: WifiMonitorSingleton 클래스가 동기화된 startMonitoring()호출하여 모니터링을 시작한다.

startMonitoring()함수에서 mConnected 변수를 확인하여 Supplicant에 연결되지 않았으면 

mWifiNative.connectToSupplicant()를 호출하여 연결한다.

연결되면 MonitorThread()를 통해 실제 모니터링할 스레드를 만들어 이것으로 Supplicant와의 연결을 모니터링한다.


참고 자료: Head First Design Patterns


반응형
Comments