LruCache 분석

4542 단어

LruCache:


LruCache는 일반 클래스로, 주요 알고리즘 원리는 최근에 사용된 대상을 강력한 인용 (즉 우리가 평소에 사용하는 대상 인용 방식) 으로 링크드 HashMap에 저장하는 것이다.캐시가 가득 차면 최근에 가장 적게 사용한 대상을 메모리에서 제거하고 get과put 방법을 제공하여 캐시를 가져오고 추가하는 작업을 완성합니다.
강 인용: 직접 대상의 인용
약한 인용: 한 대상이 약한 인용만 존재할 때, 이 대상은 수시로 GC에서 회수됩니다
소프트 인용: 하나의 대상이 하나의 소프트 인용만 존재할 때 시스템 메모리가 부족할 때 GC에서 회수합니다

LruCache 사용:

 //      
 int maxMemory = (int) (Runtime.getRuntime().totalMemory() / 1024);
       //            1/8
       int cacheSize=maxMemory/8;
        LruCache lruCache = new LruCache(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight()/1024;
            }
        };

이 코드는 주로 LruCache의 캐시 크기를 정하고,SizeOf를 다시 쓰는 것은 그림의 크기를 정합니다.(단위는 통일해야 한다)

원리:


LruCache의 핵심은 캐시 대상 목록을 유지하는 것이다. 그 중에서 목록 대상의 캐시 순서는 순서대로 정렬되고 방문하지 않은 대상이 팀 끝에 놓여 탈락할 것이다.최근 방문 대상은 팀 머리에 놓고 탈락한다.이 대기열은 LinkHashMap이 유지하고 있으며, 이것은 수조 + 양방향 체인 테이블의 데이터 구조로 이루어진다.그 중에서 양방향 체인 테이블의 구조는 접근 순서와 삽입 순서를 실현할 수 있다.이러한 특성으로 LinkHashMap의 순서 정렬이 가능합니다.
LinkHashMap 분석: LinkHashMap의 구조 함수를 보십시오
 public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
        }

여기서 매개변수 accessOrder=true가 정렬되고 false가 될 때 삽입됩니다.LinkHaspMap은 어떻게 추가하고 가져오고 삭제합니까?LruCache의 put(추가)을 보십시오.
 public final V put(K key, V value) {
 //         
        if (key == null || value == null) {
            throw new NullPointerException("key == null || value == null");
        }

        V previous;
        synchronized (this) {
            //             
            putCount++;
            //         
            size += safeSizeOf(key, value);
            //    
            previous = map.put(key, value);
            //           ,       
            if (previous != null) {
                size -= safeSizeOf(key, previous);
            }
        }
        //   ,         
        if (previous != null) {
            entryRemoved(false, key, previous, value);
        }
        //       
        trimToSize(maxSize);
        return previous;
    }

TrimToSize() 방법을 살펴보십시오.
  public void trimToSize(int maxSize) {
        while (true) {
            K key;
            V value;
            synchronized (this) {
    //  map      size   0    size  0,    
                if (size < 0 || (map.isEmpty() && size != 0)) {
                    throw new IllegalStateException(getClass().getName()
                            + ".sizeOf() is reporting inconsistent results!");
                }

                if (size <= maxSize) {
                    break;
                }
                //          
                Map.Entry toEvict = map.eldest();
                if (toEvict == null) {
                    break;
                }
            //          ,         
                key = toEvict.getKey();
                value = toEvict.getValue();
                map.remove(key);
                size -= safeSizeOf(key, value);
                evictionCount++;
            }
          //    
            entryRemoved(true, key, value, null);
        }
    }

trimToSize () 방법은 추가하면 캐시가 가득 찼는지 순환해서 판단하고 불만이 있으면 순환을 벗어나지 않으면 가장 먼저 방문한 대상을 삭제합니다.get 메서드 보기:
    public final V get(K key) {
    //  
        if (key == null) {
            throw new NullPointerException("key == null");
        }

        V mapValue;
        synchronized (this) {
           //      , get               
            mapValue = map.get(key);
            if (mapValue != null) {
                hitCount++;
                return mapValue;
            }
            missCount++;
        }

get() 누르기;
public V get(Object key) {
        Node e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
            //  
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }

이를 통해 알 수 있듯이 LruCache에서 집합 링크드 해시맵이 유지되고 이 링크드 해시맵은 방문 순서로 정렬됩니다.put () 방법을 호출하면 결합에 요소를 추가하고 TrimToSize () 를 호출하여 캐시가 가득 찼는지 판단합니다. 꽉 차면 링크드HashMap의 교체기로 팀 끝 요소, 즉 최근에 가장 적게 접근한 요소를 삭제합니다.get () 방법으로 캐시 대상에 접근할 때 링크드 HashMap의 get () 방법으로 대응하는 집합 요소를 가져오고, 이 요소를 그룹 헤더로 업데이트합니다.

좋은 웹페이지 즐겨찾기