s00ng
쏭's blog
s00ng
전체 방문자
오늘
어제
  • 분류 전체보기 (69)
    • TIL (20)
      • 실습 (3)
    • Web (6)
      • React (6)
      • Basic (0)
    • JPA (5)
    • CS (3)
      • 컴퓨터 네트워크 (3)
    • Design pattern (10)
    • AWS (5)
    • ETC (0)
    • Algorithm (0)
    • Project (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • mariaDB
  • 리전
  • 가용영역
  • solid
  • VMware
  • AWS
  • centOS 8
  • EC2
  • design pattern
  • EC2 인스턴스

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
s00ng

쏭's blog

Design pattern

[Design Pattern] Singleton Pattern

2022. 7. 20. 18:12
1. 싱글턴 패턴 정의
인스턴스가 오직 하나만 생성되는 것을 보장하고, 어디에서든 이 인스턴스에 접근할 수 있도록 하는 디자인 패턴
  • 하나의 인스턴스만을 생성하는 책임 있음
  • getInstance 메서드를 통해 모든 클라이언트에게 동일한 인스턴스 반환하는 작업 수행

싱글턴 패턴 컬레보레이션

 

2. 싱글턴 패턴 구현

- 생성자의 접근 지정자 private으로 설정

- getter를 통해 인스턴스를 제공

 

다중 스레드 애플리케이션에서 (싱글톤 구현시) 발생하는 문제

경합 조건(race condition) : 메모리와 같은 동일한 자원을 2개 이상의 스레드가 이용하려고 경합하려는 현상

※ 해결 방법 ※ 

1. 정적 변수에 인스턴스를 만들어 바로 초기화 (Eager Initialization)
2. 인스턴스를 만드는 메서드에 동기화 (Thread-Safe Initialization)

 

1) 정적 변수에 인스턴스를 만들어 바로 초기화하는 방법

public class Printer {
   // static 변수에 외부에 제공할 자기 자신의 인스턴스를 만들어 초기화
   private static Printer printer = new Printer();
   private Printer() { }
   // 자기 자신의 인스턴스를 외부에 제공
   public static Printer getPrinter(){
     return printer;
   }
   public void print(String str) {
     System.out.println(str);
   }
}

 

- static 변수
→ 객체가 생성되기 전 클래스가 메모리에 로딩될 때 만들어져 초기화가 한 번만 실행
→ 프로그램 시작~종료까지 없어지지 않고 메모리에 계속 상주하며 클래스에서 생성된 모든 객체에서 참조 가능

 

2) 인스턴스를 만드는 메서드에 동기화하는 방법

public class Printer {
   // 외부에 제공할 자기 자신의 인스턴스
   private static Printer printer = null;
   private int counter = 0;
   private Printer() { }
   // 인스턴스를 만드는 메서드 동기화 (임계 구역)
   public synchronized static Printer getPrinter(){
     if (printer == null) {
       printer = new Printer(); // Printer 인스턴스 생성
     }
     return printer;
   }
   public void print(String str) {
     // 오직 하나의 스레드만 접근을 허용함 (임계 구역)
     // 성능을 위해 필요한 부분만을 임계 구역으로 설정한다.
     synchronized(this) {
       counter++;
       System.out.println(str + counter);
     }
   }
}

 

- 인스턴스를 만드는 메서드를 임계 구역으로 변경
→ 다중 스레드 환경에서 동시에 여러 스레드가 getPrinter 메서드를 소유하는 객체에 접근하는 것을 방지

 

- 공유 변수에 접근하는 부분을 임계 구역으로 변경
→ 여러 개의 스레드가 하나뿐인 counter 변수 값에 동시에 접근해 갱신하는 것을 방지

 

3. 정적 클래스 (static class)
정적 메서드로만 이루어진 정적 클래스를 사용하면 싱글턴과 동일한 효과를 얻을 수 있음
public class Printer {
      private static int counter = 0;
      // 메서드 동기화 (임계 구역)
      public synchronized static void print(String str) {
        counter++;
        System.out.println(str + counter);
      }
}
public class UserThread extends Thread{
    // 스레드 생성
    public UserThread(String name) { super(name); }
    // 현재 스레드 이름 출력
    public void run() {
      Printer.print(Thread.currentThread().getName());
    }
}
public class Client {
    private static final int THREAD_NUM = 5;
    public static void main(String[] args) {
      UserThread[] user = new UserThread[THREAD_NUM];
      for (int i = 0; i < THREAD_NUM; i++) {
        // UserThread 인스턴스 생성
        user[i] = new UserThread((i+1));
        user[i].start();
      }
    }
}

 

 

싱글톤 패턴과의 차이점

- 정적 클래스를 이용하면 객체를 전혀 생성하지 않고 메서드를 사용한다.
- 정적 메서드를 사용하므로 일반적으로 실행할 때 바인딩되는(컴파일 타임에 바인딩되는) 인스턴스 메서드를 사용하는 것보다 성능 면에서 우수

 

정적 클래스를 사용할 수 없는 경우

- 인터페이스를 구현해야 하는 경우, 정적 메서드는 인터페이스에서 사용할 수 없음

'Design pattern' 카테고리의 다른 글

[Design Pattern] Observer Pattern  (0) 2022.08.04
[Design Pattern] Command Pattern  (0) 2022.08.01
[Design Pattern] State Pattern  (0) 2022.07.25
[Design Pattern] Strategy pattern  (0) 2022.07.13
[Design Pattern] SOLID 원칙  (0) 2022.07.01
    'Design pattern' 카테고리의 다른 글
    • [Design Pattern] Command Pattern
    • [Design Pattern] State Pattern
    • [Design Pattern] Strategy pattern
    • [Design Pattern] SOLID 원칙
    s00ng
    s00ng

    티스토리툴바