싱글 케이스 패턴: 은 일반적으로 사용되는 소프트웨어 디자인 패턴으로, 핵심 구조에는 싱글톤이라는 특수 클래스가 포함되어 있습니다. 클래스에는 인스턴스가 하나만 있습니다. 즉, 클래스에는 개체 인스턴스가 하나만 있습니다.
시스템의 일부 수업의 경우 하나의 인스턴스만 중요합니다. 예를 들어 시스템에 여러 개의 인쇄 작업이 있을 수 있지만 티켓을 판매할 때는 작업 작업이 하나만 있을 수 있으며 총 100개의 티켓이 있습니다. 동시에 티켓을 판매하는 창구가 여러 개 있지만 초과 예약이 발생하지 않도록 해야 합니다. (여기서 남은 티켓 수는 싱글톤이며 티켓 판매에는 멀티스레딩이 포함됩니다.) 창 개체를 고유화하는 메커니즘을 사용하지 않으면 여러 창이 팝업됩니다. 이러한 창에 모두 동일한 내용이 표시되면 반복 생성으로 인해 리소스가 낭비됩니다.
응용 시나리오 (출처: "Dahua Design Pattern"):
요구 사항: 프런트 엔드에 도구 상자 창을 만듭니다. 도구 상자가 나타나지 않거나 도구 상자가 하나만 나타납니다.
문제가 발생했습니다: 메뉴가 다음과 같습니다. 도구 상자 창을 만들 때마다 반복됩니다.
해결 방법 1: 객체를 생성할 때마다 먼저 if 문을 사용하여 null인지 확인합니다. null인 경우 객체를 다시 생성합니다.
요구 사항: 5곳에서 도구 상자 양식을 인스턴스화해야 하는 경우
문제 발생: 이 작은 버그는 5곳에서 수정해야 하며 코드가 반복되고 코드 활용률이 낮습니다
해결 방법 2: 사용 싱글톤 모드, 클래스의 인스턴스가 하나만 있는지 확인하고 이에 대한 전역 액세스 지점을 제공합니다.
싱글턴 모드는 게으른 스타일과 배고픈 스타일로 나눌 수 있습니다:
게으른 싱글턴 모드: 클래스가 로드될 때 초기화가 없습니다.
Hungry-style 싱글톤 모드: 클래스가 로드되면 초기화가 완료되므로 클래스 로딩은 느리지만 객체 획득 속도는 빠릅니다.
첫 번째 유형(게으른 사람, 스레드가 안전하지 않음):
public class SingletonDemo1 {private static SingletonDemo1 instance;private SingletonDemo1(){}public static SingletonDemo1 getInstance(){if (instance == null) { instance = new SingletonDemo1(); }return instance; } }
이런 게으른 로딩 작성 방법은 분명하지만 치명적인 것은 여러 스레드에서 제대로 작동할 수 없다는 것입니다.
두 번째 유형(게으른 사람, 스레드 안전):
public class SingletonDemo2 {private static SingletonDemo2 instance;private SingletonDemo2(){}public static synchronized SingletonDemo2 getInstance(){if (instance == null) { instance = new SingletonDemo2(); }return instance; } }
이러한 작성 방법은 getInstance() 메서드에 동기화된 잠금을 추가합니다. 여러 스레드에서 잘 작동하고 지연 로딩도 좋은 것 같지만 (잠금 때문에) 매우 비효율적이며 대부분의 경우 동기화가 필요하지 않습니다.
세 번째 유형(배고픈 사람):
public class SingletonDemo3 {private static SingletonDemo3 instance = new SingletonDemo3();private SingletonDemo3(){}public static SingletonDemo3 getInstance(){return instance; } }
이 방법은 클래스로더 메커니즘을 기반으로 하는 다중 스레드 동기화 문제를 방지합니다. 그러나 클래스가 로드될 때 인스턴스가 인스턴스화됩니다. 이때 인스턴스를 초기화하면 지연 로딩 효과를 얻을 수 있습니다.
네 번째 방법(hungry중국어, 변형):
public class SingletonDemo4 {private static SingletonDemo4 instance = null;static{ instance = new SingletonDemo4(); }private SingletonDemo4(){}public static SingletonDemo4 getInstance(){return instance; } }
표면적으로는 상당히 다른 것처럼 보이지만 실제로 세 번째 방법은 거의 동일하며 둘 다 클래스 초기화 중에 인스턴스화됩니다.
다섯 번째 방법(정적 내부 클래스):
public class SingletonDemo5 {private static class SingletonHolder{private static final SingletonDemo5 instance = new SingletonDemo5(); }private SingletonDemo5(){}public static final SingletonDemo5 getInsatance(){return SingletonHolder.instance; } }
이 방법도 클래스로더 메커니즘을 사용하여 인스턴스를 초기화할 때 스레드가 하나만 있는지 확인합니다. 세 번째 및 네 번째 방법과 다릅니다. 예(매우 미묘한 차이): 세 번째와 네 번째 방법은 Singleton 클래스가 로드되는 한 인스턴스가 인스턴스화된다는 것이며(지연 로딩 효과는 달성되지 않음) 이 방법은 Singleton 클래스가 로드된다는 것입니다. , 인스턴스가 반드시 초기화될 필요는 없습니다. SingletonHolder 클래스는 적극적으로 사용되지 않기 때문에 SingletonHolder 클래스는 인스턴스를 인스턴스화하기 위해 getInstance 메서드를 호출해야만 명시적으로 로드됩니다. 인스턴스를 인스턴스화하는 데 리소스가 소비되고 느리게 로드되기를 원하는 경우를 상상해 보십시오. 반면에 Singleton 클래스가 로드될 때 인스턴스화하고 싶지는 않습니다. 왜냐하면 Singleton 클래스가 다른 클래스에서 적극적으로 사용될 수 있는지 확인할 수 없기 때문입니다. places가 로드된 경우 현재 인스턴스를 인스턴스화하는 것은 분명히 부적절합니다. 현시점에서는 세 번째, 네 번째 방법보다 이 방법이 더 타당해 보인다.
여섯 번째(열거):
public enum SingletonDemo6 { instance;public void whateverMethod(){ } }
이 방법은 효과적인 Java 작성자 Josh Bloch가 옹호합니다. 이 방법은 다중 스레드 동기화 문제를 방지할 뿐만 아니라 역직렬화 및 새 객체 생성을 방지할 수도 있습니다. 장벽이 매우 높다고 하는데, 개인적으로는 1.5에서야 enum 기능이 추가되었기 때문에 이렇게 쓰면 사람들이 낯설게 느낄 수밖에 없을 것 같아요.
일곱 번째 유형(이중 인증 잠금):
public class SingletonDemo7 {private volatile static SingletonDemo7 singletonDemo7;private SingletonDemo7(){}public static SingletonDemo7 getSingletonDemo7(){if (singletonDemo7 == null) {synchronized (SingletonDemo7.class) {if (singletonDemo7 == null) { singletonDemo7 = new SingletonDemo7(); } } }return singletonDemo7; } }
이것은 일반적으로 이중 확인 잠금으로 알려진 두 번째 방법의 업그레이드 버전입니다. 자세한 소개는 다음을 참조하세요.
JDK1.5 이후에는 이중 확인 잠금이 정상적으로 싱글톤 효과를 얻을 수 있습니다.
멀티 스레드의 단일 사례 멀티 스레드 프로그램에서는 여러 스레드가 동시에 싱글톤에 액세스하는 경우 여러 인스턴스를 생성할 수 있습니다. 이때 "자물쇠"로 잠가야 합니다. 잠금, 교착 상태 및 잠금 간 통신을 포함하여 멀티스레딩에 대한 부분은 나중에 자세히 설명하겠습니다!
참조:
위 내용은 싱글톤 모드 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!