java 컬렉션 4가지 Reference

14701 단어 java 기초
public abstract class Reference {
public class SoftReference extends Reference {
public class WeakReference extends Reference {
public class PhantomReference extends Reference {
다음 표에서 요약할 수 있습니다.
등급
언제 쓰레기 수거됐어요?
용도
생존 시간
억지로 인용하다
여태껏... 하지 않았다
객체의 일반 상태
JVM 중지 시 종료
소프트 참조
메모리 부족 시
캐시
메모리 부족 시 종료
약인용
쓰레기 수거 시
개체 캐시
gc 실행 후 종료
거짓 인용
Unknown
Unknown
Unknown
 
Reference: Reference 내부에 몇 가지 중요한 속성이 있다
//  ,GC Reference 
private T referent;
//  , 
ReferenceQueue super T> queue;
/*  , ReferenceHandler  */
Reference next;

static private class Lock { };
//  , pending 
private static Lock lock = new Lock();
//  PENDING , next 
private static Reference pending = null;

내부 클래스 ReferenceHandler

ReferenceHandler는 Reference의 정적 내부 클래스로서 pending 대기열 안의 Reference 실례를 서로 다른 ReferenceQueue에 순서대로 추가하는 데 사용된다. (Reference 안의queue에 달려 있다).이 pending의 요소는 GC가 책임지고 가입합니다.주: 여기서 pending 대기열을 잠그는 것은 개인적으로 GC 스레드가 ReferenceHandler가 있는 스레드와 함께 실행될 수 있기 때문이라고 생각합니다. 예를 들어 GC가 CMS를 사용하여 동시에 수집할 때입니다.아래 코드와 같다
//  , Reference, 
private static class ReferenceHandler extends Thread {
    public void run() {
        for (;;) {

            Reference r;
            synchronized (lock) {
                if (pending != null) {
                    r = pending;
                    Reference rn = r.next;
                    //  pending , , next                     pending = (rn == r) ? null : rn;
                    r.next = r;
                } else {
                    try {
                        //  , lock.notify 
                        lock.wait();
                    } catch (InterruptedException x) { }
                    continue;
                }
            }
            // ...
            ReferenceQueue q = r.queue;
            //  Reference Queue, Queue 
            if (q != ReferenceQueue.NULL) q.enqueue(r);
        }
    }
}

ReferenceQueue 속성

//  Queue
static ReferenceQueue NULL = new Null();
//  Queue 
static ReferenceQueue ENQUEUED = new Null();

static private class Lock { };
/*  , ReferenceHandler enqueue remove poll  */
private Lock lock = new Lock();
//  
private volatile Reference extends T> head = null;
//  
private long queueLength = 0;

ReferenceQueue.enqueue


현재 대기열에 Reference를 넣는 데 사용되는 이 방법만 Reference에서 호출됩니다
boolean enqueue(Reference extends T> r) {
    synchronized (r) {
        //  
        if (r.queue == ENQUEUED) return false;
        synchronized (lock) {
            r.queue = ENQUEUED;
            //  
            r.next = (head == null) ? r : head;
            head = r;
            queueLength++;
            if (r instanceof FinalReference) {
                sun.misc.VM.addFinalRefCount(1);
            }
            //  ( remove )
            lock.notifyAll();
            return true;
        }
    }
}

어플리케이션 - WeakHashMap


WeakHashMap의 사용과 HashMap 유형은 모두 Hash+체인 테이블로 충돌을 해결한다. 유일한 차이점은 전자의 Key가 허인을 사용하여 실현된 것이다. 즉, 쓰레기를 회수할 때 회수된다. 이때 WeakHashMap은 다음 조작에서 회수된 Key에 따라 Map에서 제거된다.

Entry


Entry를 만들 때 현재 Map 속성의queue에 등록되고 키가 회수되면 Entry는queue에 저장되며 Map을 실행할 때마다 원래의 Value를 지웁니다.(expunge Stale Entries 방법으로 진행되고 단독 라인을 시작하지 않아 처리할 필요가 없습니다. 이렇게 하면 논리를 간소화하고 잠금 비용을 피할 수 있습니다)
//  WeakHashMap 
private final ReferenceQueue queue = new ReferenceQueue<>();

/*  WeakReference , , Key , WeakReference , , Key/value */
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
    //  key, WeakReference 
    V value;
    int hash;
    Entry next;
    
    Entry(Object key, V value,
          ReferenceQueue queue,
          int hash, Entry next) {
        super(key, queue);
        this.value = value;
        this.hash  = hash;
        this.next  = next;
    }
    // ...
}

좋은 웹페이지 즐겨찾기