CodeGym/Java Blog/무작위의/자바 싱글톤 클래스
John Squirrels
레벨 41
San Francisco

자바 싱글톤 클래스

무작위의 그룹에 게시되었습니다
회원
안녕! 오늘 우리는 Java Singleton 패턴을 시작으로 다양한 디자인 패턴의 세부 사항을 살펴보겠습니다. 검토해 봅시다: 일반적으로 디자인 패턴에 대해 무엇을 알고 있습니까? 디자인 패턴은 여러 가지 알려진 문제를 해결하기 위해 적용할 수 있는 모범 사례입니다. 디자인 패턴은 일반적으로 어떤 프로그래밍 언어에도 연결되지 않습니다. 실수를 피하고 바퀴의 재발명을 피하는 데 도움이 되는 일련의 권장 사항으로 생각하십시오.디자인 패턴: 싱글톤 - 1

Java에서 싱글톤이란 무엇입니까?

싱글톤은 가장 단순한 클래스 수준 디자인 패턴 중 하나입니다. 때때로 사람들은 "이 클래스는 싱글톤입니다"라고 말하는데, 이는 클래스가 싱글톤 디자인 패턴을 구현한다는 것을 의미합니다. 인스턴스화를 단일 객체로 제한하는 클래스를 작성해야 하는 경우가 있습니다. 예를 들어 로깅 또는 연결을 담당하는 클래스 싱글톤 디자인 패턴은 이를 달성하는 방법을 설명합니다. 싱글톤은 다음 두 가지 작업을 수행하는 디자인 패턴입니다.
  1. 클래스의 인스턴스가 하나만 있음을 보장합니다.

  2. 해당 인스턴스에 대한 글로벌 액세스의 단일 지점을 제공합니다.

따라서 거의 모든 싱글톤 패턴 구현의 특징인 두 가지 기능이 있습니다.
  1. 개인 생성자. 이는 클래스 자체 외부에서 클래스의 객체를 생성하는 기능을 제한합니다.

  2. 클래스의 인스턴스를 반환하는 공용 정적 메서드입니다. 이 메서드를 getInstance 라고 합니다 . 이것은 클래스 인스턴스에 대한 전역 액세스 지점입니다.

구현 옵션

싱글톤 디자인 패턴은 다양한 방식으로 적용됩니다. 각 옵션은 나름대로 좋고 나쁩니다. 항상 그렇듯이 완벽한 옵션은 없지만 하나를 위해 노력해야 합니다. 우선, 좋은 것과 나쁜 것을 구성하는 것과 디자인 패턴의 다양한 구현을 평가하는 방법에 영향을 미치는 메트릭을 결정합시다. 좋은 것부터 시작합시다. 다음은 구현을 보다 풍부하고 매력적으로 만드는 요소입니다.
  • 지연 초기화: 필요할 때까지 인스턴스가 생성되지 않습니다.

  • 간단하고 투명한 코드: 물론 이 메트릭은 주관적이지만 중요합니다.

  • 스레드 안전성: 다중 스레드 환경에서 올바른 작동.

  • 다중 스레드 환경의 고성능: 리소스를 공유할 때 스레드 차단이 거의 또는 전혀 없습니다.

이제 단점. 구현을 나쁜 관점으로 만드는 요소를 나열합니다.
  • 지연 초기화 없음: 필요 여부와 관계없이 응용 프로그램 시작 시 클래스가 로드될 때(역설적으로 IT 세계에서는 게으른 것이 좋습니다)

  • 복잡하고 읽기 어려운 코드. 이 지표도 주관적입니다. 눈에서 피가 나기 시작하면 구현이 최선이 아니라고 가정합니다.

  • 스레드 안전성이 부족합니다. 즉, "스레드 위험"입니다. 다중 스레드 환경에서 잘못된 작업입니다.

  • 다중 스레드 환경에서 성능 저하: 스레드는 리소스를 공유할 때 항상 또는 자주 서로를 차단합니다.

암호

이제 다양한 구현 옵션을 고려하고 장단점을 표시할 준비가 되었습니다.

단순한

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
가장 간단한 구현. 장점:
  • 간단하고 투명한 코드

  • 스레드 안전성

  • 다중 스레드 환경에서 고성능

단점:
  • 게으른 초기화가 없습니다.
이전의 단점을 수정하기 위한 시도에서 두 번째 구현을 얻습니다.

지연 초기화

public class Singleton {
  private static final Singleton INSTANCE;

  private Singleton() {}

  public static Singleton getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
장점:
  • 게으른 초기화.

단점:
  • 스레드로부터 안전하지 않음

이 구현은 흥미 롭습니다. 느리게 초기화할 수 있지만 스레드 안전성이 손실되었습니다. 걱정하지 마세요. 구현 3번에서 모든 것을 동기화합니다.

동기화된 액세스

public class Singleton {
  private static final Singleton INSTANCE;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
장점:
  • 게으른 초기화.

  • 스레드 안전성

단점:
  • 멀티스레드 성능 저하

훌륭한! 세 번째 구현에서는 스레드 안전성을 복원합니다! 물론 느립니다... 이제 getInstance 메서드가 동기화되어 한 번에 하나의 스레드에서만 실행할 수 있습니다. 전체 메서드를 동기화하는 대신 실제로 새 인스턴스를 초기화하는 부분만 동기화하면 됩니다. 그러나 새 인스턴스 생성을 담당하는 부분을 래핑하기 위해 단순히 동기화된 블록을 사용할 수는 없습니다 . 그렇게 하면 스레드 안전성이 보장되지 않습니다. 조금 더 복잡합니다. 아래에서 적절한 동기화를 볼 수 있습니다.

이중 확인 잠금

public class Singleton {
    private static final Singleton INSTANCE;

  private Singleton() {
  }

    public static Singleton getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton();
                }
            }
        }
        return INSTANCE;
    }
}
장점:
  • 게으른 초기화.

  • 스레드 안전성

  • 다중 스레드 환경에서 고성능

단점:
  • Java 1.5 이하 이전 버전에서는 지원하지 않음(1.5 버전부터 volatile 키워드 사용이 수정됨)

이 구현 옵션이 올바르게 작동하려면 두 가지 조건 중 하나가 충족되어야 합니다. INSTANCE 변수 final 또는 volatile 이어야 합니다 . 오늘 논의할 마지막 구현은 클래스 홀더 싱글톤 입니다 .

클래스 홀더

public class Singleton {

   private Singleton() {
   }

   private static class SingletonHolder {
       public static final Singleton HOLDER_INSTANCE = new Singleton();
   }

   public static Singleton getInstance() {
       return SingletonHolder.HOLDER_INSTANCE;
   }
}
장점:
  • 게으른 초기화.

  • 스레드 안전.

  • 다중 스레드 환경에서 고성능.

단점:
  • 올바른 작업을 위해서는 싱글톤 개체가 오류 없이 초기화된다는 보장이 필요합니다. 그렇지 않으면 getInstance 메서드 에 대한 첫 번째 호출 에서 ExceptionInInitializerError 가 발생 하고 모든 후속 호출에서 NoClassDefFoundError 가 발생합니다 .

이 구현은 거의 완벽합니다. 게으르고 스레드 안전하며 빠릅니다. 그러나 단점 목록에서 설명한 것처럼 뉘앙스가 있습니다. 싱글톤 패턴의 다양한 구현 비교:
구현 지연 초기화 스레드 안전성 멀티스레드 성능 언제 사용합니까?
단순한 - + 빠른 절대. 또는 지연 초기화가 중요하지 않은 경우일 수도 있습니다. 그러나 결코 나아지지 않을 것입니다.
지연 초기화 + - 해당 없음 멀티스레딩이 필요하지 않을 때 항상
동기화된 액세스 + + 느린 절대. 또는 멀티스레드 성능이 중요하지 않을 때 가능합니다. 그러나 결코 나아지지 않을 것입니다.
이중 확인 잠금 + + 빠른 드물게 싱글톤을 생성할 때 예외 처리가 필요한 경우(클래스 홀더 싱글톤이 적용되지 않는 경우)
클래스 홀더 + + 빠른 멀티스레딩이 필요할 때마다 싱글톤 객체가 문제 없이 생성된다는 보장이 있습니다.

싱글톤 패턴의 장단점

일반적으로 싱글톤은 예상대로 정확히 수행합니다.
  1. 클래스의 인스턴스가 하나만 있음을 보장합니다.

  2. 해당 인스턴스에 대한 글로벌 액세스의 단일 지점을 제공합니다.

그러나 이 패턴에는 다음과 같은 단점이 있습니다.
  1. 싱글톤은 단일 책임 원칙을 위반합니다. 직접적인 의무 외에도 싱글톤 클래스는 인스턴스 수를 제어합니다.

  2. 싱글톤에 대한 일반 클래스의 종속성은 클래스의 공개 계약에서 볼 수 없습니다.

  3. 전역 변수가 잘못되었습니다. 궁극적으로 싱글톤은 엄청난 전역 변수가 됩니다.

  4. 싱글톤의 존재는 애플리케이션 전체와 특히 싱글톤을 사용하는 클래스의 테스트 가능성을 감소시킵니다.

그리고 그게 다야! :) 우리는 당신과 함께 자바 싱글톤 클래스를 탐구했습니다. 이제 남은 생애 동안 프로그래머 친구들과 대화할 때 패턴이 얼마나 좋은지 언급할 수 있을 뿐만 아니라 무엇이 그것을 나쁘게 만드는지에 대해서도 몇 마디 말할 수 있습니다. 이 새로운 지식을 마스터하는 데 행운을 빕니다.

추가 자료:

코멘트
  • 인기
  • 신규
  • 이전
코멘트를 남기려면 로그인 해야 합니다
이 페이지에는 아직 코멘트가 없습니다