자바 게으름뱅이

3613 단어 자바 기반
전재 출처 를 밝 혀 주 십시오:http://blog.csdn.net/mr_liabill/article/details/48374921   리 아 빈 블 로그
단일 모드 는 흔 하 다. 면접 에서 도 직접 사례 를 쓰 라 고 한다.
단일 모드 표기 법 은 일반적으로 두 가지 로 나 뉘 는데, 게으름뱅이 식 과 굶 주 린 사람 식 이다.
굶 주 린 사람 식
public class SingleTon {
    //          static instance,    ,  static instance           ,        。
    private static SingleTon instance = new SingleTon();

    //     private ,    new SingleTon()
    private SingleTon() {
    }

    /**
     *      ,      static       ,     static 。
     *         ,  instance               ,               
     */
    public static SingleTon getInstance() {
        return instance;
    }
}

장점:
다 중 스 레 드 문 제 를 고려 할 필요 가 없습니다. 인 스 턴 스 는 정적 이기 때문에 클래스 로 딩 할 때 이미 예화 되 었 고 synchronized 로 인 한 성능 문제 도 피 할 수 있 습 니 다.
단점:
그러나 이런 방식 도 단점 이 있다. 클래스 를 초기 화 할 때 인 스 턴 스 를 구성 해 야 하기 때문에 (아직 이 인 스 턴 스 를 사용 하지 않 았 더 라 도) 특정한 조건 에서 메모리 가 소모 된다.
게으름뱅이 식
방법 1: 
volatile 기반 이중 검사 잠 금 솔 루 션
왜 아래 와 같이 이렇게 복잡 하 게 실현 해 야 하 는 지 상세 한 설명 을 참고 하 세 요.http://blog.csdn.net/guolin_blog/article/details/8860649
4. 567913. 이렇게 쓰 는 것 은 문제 가 없습니다. 사유 구조 함수 에서 어떠한 속성 도 초기 화 하지 않 았 기 때 문 입 니 다. 그렇지 않 으 면 위의 코드 를 개선 해 야 합 니 다.
여기 왜 volatile 키 워드 를 사용 해 야 합 니까?
스 레 드 thread 1 이 15 번 째 줄 에 도착 한 if 판단 에서 instance = null 이 성립 되 었 다 고 가정 하여 모두 외부 if 체 에 들 어 갔다.이때 thread 1 은 synchronized 블록 의 자 물 쇠 를 먼저 가 져 왔 기 때문에 thread 1 스 레 드 는 18 번 째 줄 의 intance = new SingleTon () 을 실행 합 니 다.이 코드 는 문제 가 바로 여기에 있다. 이 문 구 는 원자 적 으로 실 행 된 것 이 아니다.자바 에 서 는 대상 을 예화 하 는 과정 을 간단하게 말 하면 두 단계 1 로 나 눌 수 있 습 니 다. 먼저 인 스 턴 스 대상 에 게 메모리 하 나 를 할당 할 수 있 습 니 다. 2) 이 메모리 에서 인 스 턴 스 대상 의 구성원 변수 할당 (예 를 들 어 11 줄 에서 url 할당) 입 니 다.thread 1 이 1) 단 계 를 실행 하고 2) 단 계 를 실행 하지 않 았 을 때 다른 스 레 드 thread 2 가 15 번 째 줄 에 도착 했다 고 가정 합 니 다. 이때 intance 는 null 이 아니 기 때문에 thread 2 는 이 intance 대상 으로 직접 돌 아 왔 습 니 다.무슨 문제 가 있 을까요?instance 대상 의 초기 화 (변수 할당 등 작업) 가 아직 실행 되 지 않 았 습 니 다!thread 2 에서 완전히 초기 화 되 지 않 은 대상 을 직접 얻 으 면 심각 한 문 제 를 일 으 킬 수 있 습 니 다.그렇다면 volatile 키 워드 는 어떤 역할 을 합 니까?인 스 턴 스 변 수 를 volatile 로 수정 한 후 인 스 턴 스 의 쓰기 동작 '이 먼저 발생 합 니 다. (이것 은 자바 가상 컴퓨터 의 선행 발생 원칙 입 니 다) 이렇게 하면 thread 1 의 인 스 턴 스 변 수 를 완전히 초기 화한 후에 야 thread 2 가 읽 을 수 있 습 니 다. 초기 화 를 완료 하지 않 았 을 때 thread 2 는 조금 만 기 다 려 야 합 니 다.
장점:
필요 할 때 불 러 옵 니 다. 메모리 가 많이 소모 되 었 습 니 다. (필요 할 때 불 러 오기 때문에 게으름뱅이 식 이 라 고 합 니 다)
단점:
코드 가 이렇게 복잡 하고 synchronized 가 가 져 온 운행 효율 문제 도 있어 서 동기 화 방법 을 호출 하 는 것 이 많이 느 릴 것 입 니 다.
방식 2: 클래스 기반 초기 화 솔 루 션
public class SingleTon {
    private static SingleTon instance = null;

    //     private ,    new SingleTon()
    private SingleTon() {
    }

    //synchronized          ,       ,          ,    
    public static SingleTon getInstance() {
        if (null == instance) {
            synchronized (SingleTon.class) {
                if (null == instance) {
                    instance = new SingleTon();
                }
            }
        }
        return instance;
    }
}

내부 클래스 초기 화 는 지 연 됩 니 다. 외부 클래스 초기 화 는 내부 클래스 를 초기 화하 지 않 고 사용 할 때 만 내부 클래스 를 초기 화 합 니 다됐어.
두 가지 지연 초기 화 방안 총화
초기 화 지연 은 초기 화 클래스 나 인 스 턴 스 생 성 비용 을 낮 추 었 으 나 초기 화 지연 필드 에 접근 하 는 비용 을 증가 시 켰 습 니 다. 대부분의 경우 정상 적 인 초기 화 는 초기 화 지연 보다 좋 습 니 다. 인 스 턴 스 필드 에 스 레 드 보안 을 사용 하 는 지연 초기 화가 필요 하 다 면 위 에서 소개 한 volatile 기반 지연 초기 화 방안 을 사용 하 십시오.정적 필드 는 스 레 드 안전 지연 초기 화 를 사용 합 니 다. 위 에서 소개 한 클래스 기반 초기 화 방안 을 사용 하 십시오.
총결산
번 거 로 움 을 줄 이기 위해 악 한 식 을 사용 하 세 요. 하지만 저 는 보통 게으름뱅이 식 으로 필요 할 때 불 러 옵 니 다. 메모 리 를 절약 할 수 있 습 니 다. synchronized 가 일 으 키 는 효율 문제 에 대해 서 는 두 개의 스 레 드 가 동시에 getInstance 방법 을 사용 하 는 장면 이 거의 없습니다.

좋은 웹페이지 즐겨찾기