싱글 톤 패턴은 이해하기 가장 쉽고 디자인 패턴에서 직접 작성된 코드를위한 가장 쉬운 방법이지만 지식 포인트가 많지 않으므로 종종 인터뷰 질문으로 사용됩니다. 일반적으로 싱글 톤은 게으른, 배가 고프, 이중 체크 잠금, 정적 내부 클래스 및 열거의 5 가지 방법으로 작성됩니다. 학습 과정을 기록하기 위해 여기에서 몇 가지 일반적인 싱글 톤 작문 방법이 컴파일되었습니다.
Bronze 5 : (게으른로드, 스레드는 안전하지 않습니다)
싱글 톤 패턴 구현에 대해 물었을 때, 많은 사람들의 첫 번째 반응은 교과서의 동일한 가르침을 포함하여 다음 코드를 작성하는 것입니다.
공개 클래스 싱글 톤 {개인 정적 싱글 톤 인스턴스; private singleton () {} public static singleton getinstance () {if (instance == null) {instance = new Singleton (); } return 인스턴스; }}이 코드는 간단하고 간단하며 지연된로드 모드를 사용하지만 스레드는 안전하지 않습니다. 다중 스레드 환경에서 getInstance () 메소드를 호출하면 여러 스레드가 IF 문의 프로그램 코드 블록을 입력 할 수 있습니다.
게으른 스타일 : 동기화 (게으른로드, 스레드 안전하지만 효율적이지 않음)
위의 문제를 해결하기 위해 가장 쉬운 방법은 전체 GetInstance () 메소드를 동기화하도록 설정하는 것입니다.
공개 클래스 싱글 톤 {개인 정적 싱글 톤 인스턴스; private singleton () {} public static synchronized singleton getInstance () {if (instance == null) {instance = new Singleton (); } return 인스턴스; }}스레드 안전하고 지연된 하중이지만 효율적이지는 않습니다. 언제든지 getInstance () 메소드를 호출하는 스레드 만있을 수 있기 때문입니다. 그러나 동기화 된 작업은 첫 번째 호출, 즉 싱글 톤 인스턴스 객체가 처음으로 작성된 경우에만 필요합니다. 이 패턴으로 인해 싱글 톤이 생성 된 후에도 한 번에 getInstance () 메소드에 액세스 할 수 있으므로 잠재적 인 성능 문제가 발생할 수 있습니다. 이것은 이중 점검 잠금으로 이어집니다.
배고픈 스타일 : 정적 최종 필드 (비 게으른로드)
이 방법은 싱글 톤의 인스턴스가 정적 최종으로 선언되고 클래스가 처음으로 메모리에로드 될 때 초기화되므로 인스턴스 객체를 만드는 것은 스레드-안전 (JVM 구현에 의해 보장)이기 때문에 매우 간단합니다.
공개 클래스 싱글 턴 {// 개인 정적 최종 싱글 톤 인스턴스 초기화 = 새로운 싱글 톤 (); Private Singleton () {} public static singleton getinstance () {// 정적 공장 반환 인스턴스가있는 싱글 톤; }}게으른로드 모드가 아니며 클라이언트가 getInstance () 메소드를 호출하지 않더라도 클래스가로드 된 후 인스턴스가 처음부터 초기화됩니다. 예를 들어, 싱글 톤 인스턴스의 생성은 매개 변수 또는 구성 파일에 따라 다릅니다. getInstance () 전에 매개 변수를 설정하려면 특정 방법을 호출 하여이 싱글 톤 쓰기 방법을 사용하지 않도록해야합니다. 유사한 방법은 다음과 같습니다.
공개 클래스 싱글 톤 {공개 정적 최종 싱글 톤 인스턴스 = 새로운 싱글 톤 (); // 공개 Final Field Private Singleton () {}} // <Effection Java> Page 14가있는 싱글 톤Double-Check Lock + 휘발성 (Lazyload, 스레드-안전하지만 모호함)
이중 점검 잠금 패턴은 동기 블록을 사용하여 잠금 방법입니다. 프로그래머는 동기화 블록 외부에서 일단 동기화 블록 내부에 있고 동기화 블록 내부에 두 개의 체크 인스턴스 == NULL이 있기 때문에 이중 점검 잠금이라고합니다. 동기화 블록에서 다시 확인 해야하는 이유는 무엇입니까? 동기화 블록 외부에있는 경우 여러 스레드가 입력 될 수 있으므로 동기화 블록에서 보조 검증이 수행되지 않으면 여러 인스턴스 객체가 생성됩니다.
public static singleton getsingleton () {if (instance == null) {// 단일 확인 된 동기화 된 (Singleton.class) {if (instance == null) {// double checked instance = new Singleton (); }}} return instance;}이 코드는 완벽 해 보이지만 불행히도 문제가됩니다. 가장 중요한 것은 문장 인스턴스 = 새로운 싱글 톤 ()입니다. 이것은 원자 연산이 아닙니다. 실제로 JVM 의이 문장은 대략 다음과 같은 3 가지를 수행합니다.
그러나 JVM의 JIT 컴파일러에는 명령어 재정렬 최적화가 있습니다. 다시 말해, 위의 두 번째 및 세 번째 단계의 순서는 보장 될 수 없으며 최종 실행 순서는 1-2-3 또는 1-3-2 일 수 있습니다. 후자 인 경우 3과 2의 실행이 실행되지 않기 전에 스레드 2에 의해 선점됩니다. 이 시점에서 인스턴스는 이미 null이 아닌 (초기화되지 않았지만)이므로 Thread 2는 인스턴스를 직접 반환 한 다음 사용한 다음 자연스럽게 오류를보고합니다. 이를 위해서는 인스턴스 변수를 휘발성으로 선언해야합니다.
공개 클래스 싱글 톤 {개인 휘발성 정적 싱글 톤 인스턴스; // 휘발성 프라이빗 싱글 톤 () {} 공개 정적 싱글 톤 GetSingleton () {if (instance == null) {synchronized (singleton.class) {if (instance == null) {instance = new Singleton (); }} return instance; }}그러나 Java 1.5 이전의 휘발성 듀얼 체크 잠금에 여전히 문제가 있음에 주목하는 것이 중요합니다. 이 문제는 Java 1.5에서만 고정되어 있으므로 그 후 휘발성을 사용할 수 있습니다.
정적 내부 클래스 : IODH, 초기화-주문형 홀더
이 패턴은 Java의 정적 내부 클래스와 다중 스레드 기본 동기화 잠금 지식을 결합하고 대기 시간로드 및 스레드 안전을 영리하게 구현합니다.
공개 클래스 싱글 톤 {private singleton () {} private static class lazyholder {private static final singleton instance = new Singleton (); } public static singleton getInstance () {// Wikipedia의 return lazyholder.instance; }}정적 내부 클래스는 외부 클래스의 정적 부분과 동일합니다. 객체는 외부 클래스 객체에 의존하지 않으므로 직접 만들 수 있습니다. 정적 내부 클래스는 처음으로 사용될 때만 재현됩니다.
다중 스레드 기본 동기화 잠금
우리 모두가 알고 있듯이, 다중 스레드 개발에서 동시성 문제를 해결하기 위해 동기화 된 제어를 위해 뮤 테스를 추가하기 위해 동기화 된 경우 주로 동기화됩니다. 그러나 경우에 따라 JVM은 이미 암시 적으로 동기화를 수행하며 이러한 경우 동기화 제어를 수동으로 수행 할 필요가 없습니다. 이러한 상황에는 다음이 포함됩니다 .
1. 정적 이니셜 라이저로 데이터를 초기화 할 때 (정적 필드 또는 정적 {} 블록에서의 이니셜 라이저)
2. 최종 필드에 액세스 할 때
3. 스레드를 만들기 전에 객체를 만들 때
4. 스레드가 객체를 볼 수 있으면 처리됩니다.
열거적
Java 1.5에서 시작하여 단일 요소가 포함 된 열거 형식을 작성하십시오.
공개 열거 싱글 톤 {instance;}이 방법은 공개 도메인 방법과 기능적으로 유사하지만, 더 간결하고 직렬화 메커니즘을 무료로 제공하여 복잡한 직렬화 또는 반사 공격에 직면 할 때에도 여러 차례의 인스턴스화를 방지합니다. 이 접근법은 널리 채택되지 않았지만 단일 요소의 열거 유형은 싱글 톤을 구현하는 가장 좋은 방법이되었습니다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1. 정적 결승의 세부 사항은 무엇입니까?
2. 정적 필드에서의 할당 초기화는 순서대로 및 정적 코드 블록입니까?
3. 정적 내부 클래스를위한 싱글 톤 패턴을 작성하는 방법
4. Java EE 설계 패턴 분석 및 응용 프로그램의 예제가 실제로 Lazyload 효과를 가지고 있습니까?
위는이 기사의 모든 내용입니다. 이 기사의 내용이 모든 사람의 연구 나 업무에 도움이되기를 바랍니다. 또한 wulin.com을 더 지원하기를 바랍니다!