LruCache 기본 원리 와 분석
8648 단어 nginx
LRU 는 모두 Least Recently Used 라 고 하 는데, 즉 최근 에 가장 적 게 사용 하 는 것 이다.
LRU 알고리즘 은 캐 시 공간 이 가득 찼 을 때 최근 에 가장 적 게 사용 한 데 이 터 를 캐 시 공간 에서 삭제 하여 사용 가능 한 캐 시 공간 을 늘 려 새 데 이 터 를 캐 시 하 는 것 입 니 다.
이 알고리즘 은 내부 에 캐 시 목록 이 있 습 니 다. 캐 시 데이터 가 접근 할 때마다 이 데 이 터 는 목록 의 끝 부분 에 언급 됩 니 다. 매번 이 럴 때마다 목록 의 머리 데 이 터 는 최근 에 가장 자주 사용 되 지 않 습 니 다. 캐 시 공간 이 부족 할 때 열 표 머리의 캐 시 데 이 터 를 삭제 합 니 다.
2. LruCache 의 사용
//
int maxMemory=(int)(Runtime.getRuntime().maxMemory()/1024);
int cacheSize=maxMemory/8;
private LruCache mMemoryCache;
// LruCache 1/8
mMemoryCache = new LruCache(mCacheSize){
// , Bitmap
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight()/1024;
}
};
3. LruCache 부분 소스 코드 분석
LruCache 는 LinkedHashMap 의 한 특성 (accessOrder = true 접근 순서 기반) 을 이용 하여 LinkedHashMap 의 데이터 조작 잠 금 에 대한 캐 시 정책 을 추가 합 니 다.
링크 드 HashMap 의 기본 구조 적 인 파 라 메 터 는 기본 삽입 순서 입 니 다. 즉, 당신 이 삽입 한 순서 가 무엇 인지, 읽 은 순서 가 무엇 인지 말 합 니 다. 하지만 방문 순서 도 있 습 니 다. 즉, 키 를 방문 했다 는 것 입 니 다. 이 키 는 맨 뒤로 달 려 갔습니다.
LruCache 의 데이터 캐 시 는 메모리 에 있 습 니 다.
/**
* @param maxSize for caches that do not override {@link #sizeOf}, this is
* the maximum number of entries in the cache. For all other caches,
* this is the maximum sum of the sizes of the entries in this cache.
*/
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap(0, 0.75f, true);
}
LinkedHashMap 매개 변수 소개:
2. 데이터 추가 LruCache. put (K key, V value)
/**
* Caches {@code value} for {@code key}. The value is moved to the head of
* the queue.
*
* @return the previous value mapped by {@code key}.
*/
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++;
//safeSizeOf(key, value)。
// 1, 1.
// , size , sizeOf(key, value)
size += safeSizeOf(key, value);
// map , , , , null
previous = map.put(key, value);
// ,
if (previous != null) {
size -= safeSizeOf(key, previous);
}
}
//entryRemoved() ,
if (previous != null) {
entryRemoved(false, key, previous, value);
}
trimToSize(maxSize);
return previous;
}
put () 방법 은 논리 가 많 지 않 은 것 을 볼 수 있 습 니 다. 중요 한 것 은 캐 시 대상 을 추가 한 후에 trimToSize () 방법 을 사용 하여 캐 시가 가득 찼 는 지 여 부 를 판단 하 는 것 입 니 다. 가득 차 면 최근 에 가장 적 게 사용 한 데 이 터 를 삭제 해 야 합 니 다.
2.trimToSize(int maxSize)
/**
* Remove the eldest entries until the total of remaining entries is at or
* below the requested size.
*
* @param maxSize the maximum size of the cache before returning. May be -1
* to evict even 0-sized elements.
*/
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!");
}
// size , ,
if (size <= maxSize) {
break;
}
// , , , map 。
Map.Entry toEvict = map.eldest();
if (toEvict == null) {
break;
}
key = toEvict.getKey();
value = toEvict.getValue();
map.remove(key);
size -= safeSizeOf(key, value);
// +1
evictionCount++;
}
entryRemoved(true, key, value, null);
}
}
/**
* Returns the eldest entry in the map, or {@code null} if the map is empty.
*
* Android-added.
*
* @hide
*/
public Map.Entry eldest() {
Entry eldest = header.after;
return eldest != header ? eldest : null;
}
trimToSize () 방법 은 캐 시 크기 가 최대 치 보다 작 을 때 까지 링크 드 HashMap 의 첫 번 째 요 소 를 계속 삭제 합 니 다.
3.LruCache.get(K key)
/**
* Returns the value for {@code key} if it exists in the cache or can be
* created by {@code #create}. If a value was returned, it is moved to the
* head of the queue. This returns null if a value is not cached and cannot
* be created.
* key , , ,
*
*/
public final V get(K key) {
if (key == null) {
throw new NullPointerException("key == null");
}
V mapValue;
synchronized (this) {
// LinkedHashMap 。
mapValue = map.get(key);
if (mapValue != null) {
hitCount++;
return mapValue;
}
missCount++;
}
/*
*
* create(K key) null
* create(K key) ,
*/
/*
* Attempt to create a value. This may take a long time, and the map
* may be different when create() returns. If a conflicting value was
* added to the map while create() was working, we leave that value in
* the map and release the created value.
* : key , creat(key) 。
* create(key) null, 。
*/
V createdValue = create(key);
if (createdValue == null) {
return null;
}
// create(key) , , 。
synchronized (this) {
createCount++;
mapValue = map.put(key, createdValue);
if (mapValue != null) {
// There was a conflict so undo that last put
map.put(key, mapValue);
} else {
size += safeSizeOf(key, createdValue);
}
}
if (mapValue != null) {
entryRemoved(false, key, createdValue, mapValue);
return mapValue;
} else {
trimToSize(maxSize);
return createdValue;
}
}
LruCache 의 get () 방법 을 호출 하여 집합 에 있 는 캐 시 대상 을 가 져 올 때 이 요 소 를 한 번 방문 한 것 을 의미 합 니 다. 대기 열 을 업데이트 하고 전체 대기 열 을 방문 순서에 따라 정렬 합 니 다. 이 업데이트 과정 은 LinkedHashMap 의 get () 방법 에서 이 루어 집 니 다.
총결산
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
간단! Certbot을 사용하여 웹 사이트를 SSL(HTTPS)화하는 방법초보자가 인프라 주위를 정돈하는 것은 매우 어렵습니다. 이번은 사이트를 간단하게 SSL화(HTTP에서 HTTPS통신)로 변경하는 방법을 소개합니다! 이번에는 소프트웨어 시스템 Nginx CentOS7 의 환경에서 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.