(3/23) 단일 디자인 모델

2871 단어
말하자면 JVM에서 실례적인 대상만 단일 디자인 모델이 존재하고 응용이 넓다는 것을 보장한다. 장점은 다음과 같다. 1. 특정한 대상이 비교적 크고 응용이 빈번하면 단일 사례를 사용하면 매우 큰 시스템 비용을 절약할 수 있다. 2. new를 한 번 사용하면 더 이상 new를 필요로 하지 않고 시스템 메모리의 사용 빈도를 낮추며 쓰레기 회수 메커니즘의 작업을 줄일 수 있다.
3. 어떤 경우 하나의 종류가 전체 국면을 통제해야 할 때 하나의 예가 필요하다.(한 나라에는 최고 지도자가 한 명밖에 없다. 말이 많으면 누구의 말을 듣겠는가?)
간단한 게으름뱅이
public class Single {
	private static Single s = null;// , , null, 
	private Single(){}
	// 
	public static Single getInstace(){
		if(s==null)
			s = new Single();
		return s;
	}
	
	// , 
	public Object readResolve(){
		return s;
	}
}

이상의 실현 방식은 일단 다중 스레드 환경에 처하면 안전 위험이 발생할 수 있다. A, B 두 스레드, A는 s==null을 판단한 후에 new를 준비하고 있다. 아직 new가 끝나지 않으면 B 스레드로 전환한다. B 스레드 new가 끝난 후에 A 스레드를 자르고 계속 new를 준비하면 위험이 발생한다.
기본 솔루션:
스레드 자물쇠를 증가하여 안전을 보증합니다.
<span style="white-space:pre">	</span>public class Single {
		private static Single s = null;
		private Single(){}

		public synchronized static Single getInstace(){
			if(s==null)
				s = new Single();
			return s;
		}
	
		public Object readResolve(){
			return s;
		}
}

이 방법은 안전 문제를 해결했지만 희생의 대가가 좀 있습니다. 다중 라인이 안전하지 않은 문제 때문에 실례를 판단하여null로 인용한 후 new로 갑니다
실례 대상 과정 중 발생한 것이기 때문에 우리는 첫 번째 창설 대상을 확보할 때 라인의 안전을 확보하면 된다
개선 사항:
public static Single getInstace(){
		if(s==null){		// 
			synchronized(Single.class){		
				if(s == null)	// 
					s = new Single();
			}
		}
			
		return s;
	}

synchronized를 내부에 추가했습니다. 즉, 호출할 때 자물쇠를 추가할 필요가 없고 s가null이고 대상을 만들 때만 자물쇠를 추가할 수 있으며 성능이 어느 정도 향상되었습니다.
문제가 해결된 것 같지만 위험이 나타날 수 있다.자바 명령에서 대상을 만드는 것과 값을 부여하는 작업은 분리되어 진행된다. 즉, s = new Single ().문장은 두 단계로 나누어 집행된다.그러나 JVM은 양자의 순서를 보장하지 않는다. JVM이 먼저 공간을 분배한 다음에 s에게 값을 부여한 다음에 Single 실례를 초기화하면 문제가 발생할 수 있다. 예를 들어 A, B 두 개의 라인 1.A, B는 동시에 첫 번째if판단을 통해 2.A라인은 잠금 대상을 먼저 획득하고 s==null, s=new Single () 를 실행합니다.3. 단, JVM 스레드는single 실례의 공백 메모리를 분배하고 값을 부여하지만 초기화s가 있으면 A스레드는synchronized를 떠난다. 4.B라인은 자물쇠 대상을 받았지만 이때의 s!=null, 그래서 B라인이 5.그러면 getInstace () 프로그램을 호출하면 초기화되지 않아 문제가 발생하기 때문에 다선정 환경에서 게으름뱅이식의 위험은 근절하기 어려우므로 개발은 일반적으로 사용하지 않고 굶주림식(면접은 게으름뱅이식, 기술 함량이 높음)을 사용한다.
아사자식
public class Single {
	private static final Single s = new Single();
	public static Single getInstance(){
		return Single.s;
	}
}

내부 클래스로 단례를 한층 더 유지할 수 있다.
public class Single {
	private Single(){}
	
	public static class SingleChild{
		private static Single s = new Single();
	}
	
	public static Single getInstance(){
		return SingleChild.s;
	}
	
	public Object ReadResolve(){
		return getInstance();
	}
}

요약:
1. 단일 디자인 모델은 간단해 보이지만 실현하기가 쉽지 않다. 게으름뱅이식이라는 방식은 반드시 신중하게 사용해야 한다. 개발하고 사용하지 않지만 반드시 면접을 봐야 한다.
2.synchronized의 사용은 반드시 성분을 고려하여 마땅히 있어야 할 곳에 두어야 한다. 이것저것 고려하지 말고 안전을 해결하고 효율을 희생해야 한다.

좋은 웹페이지 즐겨찾기