당신 은 정말 자바 단일 모드 를 이해 하 였 습 니까?

11972 단어 자바일례패턴
배경
최근 에 디자인 모델 을 배 웠 습 니 다.사례 모델 을 볼 때 저 는 처음에 사례 모델 을 직접 잘 알 고 실현 하 는 것 도 간단 하 다 고 생각 했 습 니 다.그러나 실제 적 으로 사례 모델 은 여러 가지 변종 이 있 고 다 중 스 레 드 에서 스 레 드 안전 문제 와 관련 되 었 습 니 다.그러면 본 고 는 사례 모델 에 대해 잘 이야기 하고 전형 적 인 세 가지 실현 방식 을 말씀 드 리 겠 습 니 다.굶 주 린 사람 식,게 으 른 사람 식,등록 식.그리고 다 중 스 레 드 에서 발생 할 수 있 는 스 레 드 안전 문 제 를 해결 합 니 다.
2.기본 개념
1.왜 단일 모드 를 사용 합 니까?
우리 의 일상적인 업무 에서 많은 대상 들 이 매우 중요 한 시스템 자원 을 점용 한다.예 를 들 어 IO 처리,데이터 베이스 작업 등 이다.그러면 우 리 는 이런 대상 들 이 하나의 공용 인 스 턴 스,즉 단일 사례 만 사용 하 는 것 을 제한 해 야 한다.
2.단일 모델 의 실현 방식
구조 함수 의 사유 화 는 다른 종류의 유일한 공용 실례 밖의 실례 를 생 성 하 는 것 을 방지한다.또한 단일 클래스 는 final 로 정의 되 어야 합 니 다.즉,단일 클래스 는 계승 할 수 없습니다.그 하위 클래스 를 계승 할 수 있다 면 인 스 턴 스 를 만 들 수 있 고 유일한 인 스 턴 스 의 취지 에 어 긋 나 기 때 문 입 니 다.
클래스 의 정적 변 수 는 단일 인 스 턴 스 의 인용 을 저장 합 니 다.
하나의 인 스 턴 스 의 인용 을 얻 기 위해 공 통 된 정적 방법
3.단일 모드 UML 도표

4.단일 모델 의 전형 적 인 실현 방식
4.567917.굶 주 린 사람 식:처음부터 인 스 턴 스 를 만 들 고 호출 할 때마다 바로 돌아 갑 니 다.전형 적 인'공간 으로 시간 을 바 꿉 니 다'4.567917.게으름뱅이 식:로 딩 지연,첫 번 째 호출 할 때 만 로 딩 한 다음 에 돌아 갑 니 다.이후 의 매번 호출 은 바로 돌아 갑 니 다.전형 적 인'시간 으로 공간 을 바꾼다'는 것 은 다 중 스 레 드 환경 에서 스 레 드 안전 문 제 를 해결 하 는 데 주의해 야 한다4.567917.등록 식:하나의 사례 모델 을 유지 하 는 것 은 주로 수량 적 인 확장 입 니 다.스 레 드 안전 한 map 를 통 해 하나의 사례 를 저장 합 니 다.이렇게 호출 할 때 이 사례 가 이미 만 들 어 졌 는 지 판단 하고 그렇지 않 으 면 바로 돌아 갑 니 다.그렇지 않 으 면 map 에 등록 한 다음 에 돌아 갑 니 다3.굶 주 린 한식-코드 실현
1.일례 류

package com.hafiz.designPattern.singleton;
/**
* Desc:     -   
* Created by hafiz.zhang on 2017/9/26.
*/
public class Singleton1 {
//         ,        
private static volatile Singleton1 instance = new Singleton1();
private Singleton1() {
//        
System.out.println("--              --");
}
public static Singleton1 getInstance() {
System.out.println("--                  --");
return instance;
}
}
2.테스트 클래스

public class DesignPatternTest {
@Test
public void testSingleton1() {
System.out.println("-----------------           --------------");
Singleton1 instance1 = Singleton1.getInstance();
System.out.println("       ");
Singleton1 instance2 = Singleton1.getInstance();
System.out.println("instance1 instance2       ?" + (instance1 == instance2));
System.out.println("-----------------           --------------");
}
}
3.테스트 결과

4.게으름뱅이 식-코드 실현
1.일례 류

package com.hafiz.designPattern.singleton;
/**
* Desc:    -   
* Created by hafiz.zhang on 2017/9/26.
*/
public class Singleton2 {
//         ,        
private static Singleton2 instance = null;
//        
private Singleton2() {
System.out.println("--              --");
}
public static Singleton2 getInstance() {
System.out.println("--             --");
if (instance == null) {
System.out.println("--          ,      --");
instance = new Singleton2();
}
return instance;
}
}
2.테스트 클래스

public class DesignPatternTest {
@Test
public void testSingleton2() {
System.out.println("-----------------           --------------");
Singleton2 instance1 = Singleton2.getInstance();
System.out.println("       ");
Singleton2 instance2 = Singleton2.getInstance();
System.out.println("instance1 instance2       ?" + (instance1 == instance2));
System.out.println("-----------------           --------------");
}
}
3.테스트 결과

세심 한 학생 들 은 이러한 실현 방식 이 다 중 스 레 드 환경 에서 스 레 드 안전 문제 가 있다 는 것 을 발견 했다.두 개 또는 여러 개의 스 레 드 가 intance 를 모두 null 로 판단 한 다음 에 여러 번 인 스 턴 스 를 만 들 었 고 사례 에 부합 되 지 않 는 사상 을 만 들 었 기 때문에 우 리 는 이 를 개선 할 수 있다.
5.게으름뱅이 식 개선 1-코드 실현
원리:JDK 의 synchronized 동기 코드 블록 을 사용 하여 게으름뱅이 스 레 드 보안 문 제 를 해결 합 니 다.
1.일례 류

package com.hafiz.designPattern.singleton;
/**
* Desc:    -   
* Created by hafiz.zhang on 2017/9/26.
*/
public class Singleton2 {
//         ,        
private static Singleton2 instance = null;
//        
private Singleton2() {
System.out.println("--              --");
}

public static Singleton2 getInstance() {
System.out.println("--             --");
     if (instance != null) {
        System.out.println("--           ,    --");
 return instance;
     }
synchronized (Singleton2.class) {
   if (instance == null) {
  System.out.println("--          ,      --");
  instance = new Singleton2();
   }
}
return instance;
}
} 
2.테스트 결과

6.게으름뱅이 식 개선 2-코드 구현
원리:JVM 에 포 함 된 동기 화 와 클래스 내부 클래스 를 사용 하여 해결 합 니 다.JVM 에 포 함 된 동기 화 는 다 중 스 레 드 상황 에서 스 레 드 안전 문 제 를 해결 하고 클래스 내부 클래스 는 사용 할 때 만 로드(로드 지연)문 제 를 해결 합 니 다.
1.JVM 에 포 함 된 동기 화 는 어떤 것 이 있 습 니까?
정적 초기 화 기(정적 필드 나 static{}정적 코드 블록 초기 화 기)에서 데 이 터 를 초기 화 할 때
final 필드 에 접근 할 때
스 레 드 를 만 들 기 전에 대상 을 만 들 때
스 레 드 가 처리 할 대상 을 볼 수 있 을 때
2.클래스 내부 클래스 는 무엇 입 니까?
static 수식 이 있 는 구성원 식 내부 클래스.static 수식 이 없 는 구성원 식 내부 클래스 를 대상 급 내부 클래스 라 고 합 니 다.
클래스 내부 클래스 는 외부 클래스 의 static 성분 에 해당 하 며,그의 대상 은 외부 클래스 대상 과 의존 관계 가 없 기 때문에 직접 만 들 수 있 으 며,대상 급 내부 클래스 의 인 스 턴 스 는 외부 대상 인 스 턴 스 에 연결 되 어 있 습 니 다.
클래스 내부 클래스 에서 정적 인 방법 을 정의 할 수 있 습 니 다.정적 방법 에 서 는 외부 클래스 의 정적 구성원 방법 이나 구성원 변수 만 참조 할 수 있 습 니 다.
클래스 내부 클래스 는 외부 클래스 에 해당 하 는 구성원 으로 처음 사 용 될 때 만 불 러 옵 니 다.
3.일례 류

package com.hafiz.designPattern.singleton;
/**
* Desc:    -     
* Created by hafiz.zhang on 2017/9/26.
*/
public class Singleton3 {
private static class Singleton4 {
private static Singleton3 instance;
static {
System.out.println("--        --");
instance = new Singleton3();
}
private Singleton4() {
System.out.println("--            --");
}
}
private Singleton3() {
System.out.println("--      --");
}
public static Singleton3 getInstance() {
System.out.println("--            --");
Singleton3 instance;
System.out.println("---------------------------");
instance = Singleton4.instance;
System.out.println("    ");
return instance;
}
}
4.테스트 클래스

package com.hafiz.www;
import com.hafiz.designPattern.observer.ConcreteObserver;
import com.hafiz.designPattern.observer.ConcreteSubject;
import com.hafiz.designPattern.singleton.Singleton1;
import com.hafiz.designPattern.singleton.Singleton2;
import com.hafiz.designPattern.singleton.Singleton3;
import com.hafiz.designPattern.singleton.Singleton4;
import com.hafiz.designPattern.singleton.Singleton4Child1;
import com.hafiz.designPattern.singleton.SingletonChild2;
import org.junit.Test;
/**
* Desc:    demo     
* Created by hafiz.zhang on 2017/7/27.
*/
public class DesignPatternTest {
@Test
public void testSingleton3() {
System.out.println("-----------------             --------------");
Singleton3 instance1 = Singleton3.getInstance();
System.out.println("       ");
Singleton3 instance2 = Singleton3.getInstance();
System.out.println("instance1 instance2       ?" + (instance1 == instance2));
System.out.println("-----------------             --------------");
}
}
5.테스트 결과

7.등록 식-코드 실현
1.기본 클래스

package com.hafiz.designPattern.singleton;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Desc:     -   
* Created by hafiz.zhang on 2017/9/26.
*/
public class Singleton4 {
private static Map<String, Singleton4> map = new ConcurrentHashMap<>();
protected Singleton4() {
System.out.println("--          --");
}
public static Singleton4 getInstance(String name) {
if (name == null) {
name = Singleton4.class.getName();
System.out.println("--name  ,     :--" + Singleton4.class.getName());
}
if (map.get(name) != null) {
System.out.println("name      ,    ");
return map.get(name);
}
System.out.println("name       ,   ,   ");
try {
Singleton4 result = (Singleton4)Class.forName(name).newInstance();
map.put(name, result);
return result;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public Map<String, Singleton4> getMap() {
return map;
}
}
2.하위 클래스 1

package com.hafiz.designPattern.singleton;
/**
* Desc:
* Created by hafiz.zhang on 2017/9/26.
*/
public class Singleton4Child1 extends Singleton4 {

public static Singleton4Child1 getInstance() {
return (Singleton4Child1) Singleton4.getInstance("com.hafiz.designPattern.singleton.Singleton4Child1");
}
}
3.하위 클래스 2

package com.hafiz.designPattern.singleton;
/**
* Desc:
* Created by hafiz.zhang on 2017/9/26.
*/
public class SingletonChild2 extends Singleton4 {
public static SingletonChild2 getInstance() {
return (SingletonChild2) Singleton4.getInstance("com.hafiz.designPattern.singleton.SingletonChild2");
}
}
4.테스트 클래스

public class DesignPatternTest {
@Test
public void testSingleton4() {
System.out.println("-----------------           --------------");
System.out.println("       ");
Singleton4 instance1 = Singleton4.getInstance(null);
System.out.println("res:" + instance1);
System.out.println("       ");
Singleton4Child1 instance2 = Singleton4Child1.getInstance();
System.out.println("res:" + instance2);
System.out.println("       ");
SingletonChild2 instance3 = SingletonChild2.getInstance();
System.out.println("res:" + instance3);
System.out.println("       ");
SingletonChild2 instance4 = new SingletonChild2();
System.out.println("res:" + instance4);
System.out.println("    Map      ");
Map<String, Singleton4> map = instance1.getMap();
for (Map.Entry<String, Singleton4> item : map.entrySet()) {
System.out.println("map-item:" + item.getKey() + "=" + item.getValue());
}
System.out.println("instance1 instance2       ?" + (instance1 == instance2));
System.out.println("-----------------           --------------");
}
}
5.테스트 결과

이 솔 루 션 의 단점:기본 적 인 구조 함수 가 하위 클래스 에 공개 되 었 습 니 다(proctected).좋 은 솔 루 션 을 가 진 박 우 는 토론 하고 지도 할 수 있 습 니 다~
8.총화
본 고 를 통 해 우 리 는 단일 모델 이 무엇 인지,전형 적 인 단일 모델 을 어떻게 우아 하 게 실현 하 는 지,스 레 드 안전 을 가 진 단일 모델 을 어떻게 확대 하고 개발 하 는 지 알 게 되 었 다.우리 의 향후 개발 에 매우 도움 이 되 고 단일 모델 도 더욱 잘 알 게 해 준다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기