C
c 로 만든 LRU cache 이다. Least Requested Used 제일 적게 요청되고, 사용되어진 녀석이 cache 가 max 일 때 먼저 사라진다.Linked List 로 구현한 queue 를 이용해 구현하고 있다. 그리고 cache 안에서 검색을 위해 hash table 을 이용하고 있다.
http://www.geeksforgeeks.org/implement-lru-cache/
Java
안드로이드 관련 cache 소스는 아래에서 확인할 수 있다.이녀석과 구글의 LRUCache class 를 비교해서 보면 이해가 쉬울 것이다.
설명이 필요하다면
를 참고하자.
아래는 LazyList/MemoryCache.java 에 대한 주석이 조금 더 들어간 source code 이다.
import android.graphics.Bitmap;
import android.util.Log;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* source from : https://github.com/thest1/LazyList/blob/master/src/com/fedorvlasov/lazylist/MemoryCache.java
*
* This memory cache is modified in reference to the Caching Bitmap
* {@ref: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html} article
*
*
*/
public class MemoryCache {
private static final String TAG = "MemoryCache";
private Map<String, Bitmap> cache= Collections.synchronizedMap(
new LinkedHashMap<String, Bitmap>(10, 1.5f, true));//Last argument true for LRU ordering
private long size = 0;//current allocated size
private long limit = 0;//max memory in bytes
public MemoryCache(){
// http://javarevisited.blogspot.kr/2012/01/find-max-free-total-memory-in-java.html
//
//use 25% of available heap size
setLimit(Runtime.getRuntime().maxMemory()/4);
}
public void setLimit(long new_limit){
limit = new_limit;
Log.i(TAG, "MemoryCache will use up to " + limit / 1024. / 1024. + "MB");
}
public Bitmap get(String id){
try{
if(!cache.containsKey(id))
return null;
//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78
return cache.get(id);
}catch(NullPointerException ex){
ex.printStackTrace();
return null;
}
}
public void put(String id, Bitmap bitmap){
try{
if(cache.containsKey(id))
size -= getSizeInBytes(cache.get(id));
cache.put(id, bitmap);
size += getSizeInBytes(bitmap);
checkSize();
}catch(Throwable th){
th.printStackTrace();
}
}
private void checkSize() {
Log.i(TAG, "cache size=" + size + " length=" + cache.size());
if(size > limit){
synchronized(cache){ //namh added
Iterator<Entry<String, Bitmap>> iter = cache.entrySet().iterator();//least recently accessed item will be the first one iterated
while(iter.hasNext()){
Entry<String, Bitmap> entry = iter.next();
size -= getSizeInBytes(entry.getValue());
iter.remove();
if(size<=limit)
break;
}
}
Log.i(TAG, "Clean cache. New size " + cache.size());
}
}
public void clear() {
try{
//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78
// http://stackoverflow.com/questions/12218976/cannot-draw-recycled-bitmaps-when-displaying-bitmaps-in-gallery-attached-to-ad
//
// recycle() should be called when no reference gets the bitmap.
// but in this case, when the view is showed, always some bitmap is being used.
// Thus, you must NOT recycle() here.
cache.clear();
size = 0;
//namh what about this?
//System.gc();
}catch(NullPointerException ex){
ex.printStackTrace();
}
}
long getSizeInBytes(Bitmap bitmap) {
if(bitmap==null)
return 0;
return bitmap.getRowBytes() * bitmap.getHeight();
}
// the destructor should also handle the memory in case it still holds memory
protected void finalize() {
// http://stackoverflow.com/questions/8996655/android-bitmap-and-memory-management
//
synchronized(cache){
// get HashMap entry iterator
Iterator<Entry<String, Bitmap>> iter = cache.entrySet().iterator();
while(iter.hasNext()) {
// get entry pair
Entry<String, Bitmap> entry = iter.next();
// get Bitmap object
Bitmap image = entry.getValue();
// recycle if...
if(image != null && !image.isRecycled()) {
image.recycle();
image = null;
}
}
cache.clear();
}// end of synchronized
}
}
댓글 없음:
댓글 쓰기