2012-02-29 4 views
3

나는 이것으로 완전히 곤란을 겪고있다. 나는 다운로드 한 비트 맵 이미지의 캐시를 관리하는 정적 클래스를 가지고있다. 이 클래스는 동시 액세스 가능성이있는 여러 스레드에서 액세스합니다. 내가 최대 캐시 크기 (공동 선두로부터)에 도달하면 가장 오래된 비트 맵을 캐시에서 제거되도록 롤링 캐시를 구현하기 위해 노력하고있어캐싱 메커니즘이 예상대로 작동하지 않는 이유는 무엇입니까?

public class BitmapCache { 
    private static final int MAX_NUMBER_BITMAPS_TO_CACHE = 30; 
    private static Map<String, Bitmap> bitmapCache = new HashMap<String, Bitmap>(); 
    private static List<String> cachedBitmapUrlsOrder = new ArrayList<String>(); 

    private BitmapCache(){} 

    public static synchronized void addBitmapToCache(String url, Bitmap bitmap) { 
     if (bitmapCache.size() >= MAX_NUMBER_BITMAPS_TO_CACHE) { 
      Log.i("MyApp", "Max cache size reached. Removing oldest bitmap. Size = " + bitmapCache.size()); 
      String oldestUrl = cachedBitmapUrlsOrder.remove(0); 
      bitmapCache.remove(oldestUrl); 
     } 
     bitmapCache.put(url, bitmap); 
     cachedBitmapUrlsOrder.add(url); 
    } 

    public static int size() { 
     return bitmapCache.size(); 
    } 

    public static Bitmap get(String url) { 
     return bitmapCache.get(url); 
    } 

    public synchronized static void clearCache() { 
     bitmapCache.clear(); 
    } 
} 

: 여기에 구현입니다. 내 응용 프로그램을 실행하면 다음과 같은 출력을 제공합니다

02-29 23:00:26.590: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 30 
02-29 23:00:26.600: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 30 
02-29 23:00:26.720: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 30 
02-29 23:00:26.790: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 30 
02-29 23:00:26.820: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 31 
02-29 23:00:26.850: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 31 
02-29 23:00:27.050: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 32 
02-29 23:00:27.070: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 32 
02-29 23:00:27.100: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 33 
02-29 23:00:27.130: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 34 
02-29 23:00:27.170: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 35 
02-29 23:00:27.210: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 35 
02-29 23:00:27.330: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 35 
02-29 23:00:27.360: I/MyApp(10789): Max cache size reached. Removing oldest bitmap. Size = 35 

코드가 제대로 로깅 시작 '에 도달 최대 캐시 크기를'캐시 크기가 30에 도달하고 몇 가지 실행을 위해이 유지 될 때. 그러나 이상하게도 35까지 증가하기 시작합니다.이 시점에서 수백 개의 출력이 더 많이 남아 있습니다. 나는 그것을 35 이상으로 증가시킬 수 없다.

나의 구현에있어 잘못된 점은 무엇인가? addBitmapToCache 메서드가 동기화되면 캐시 크기가 최대 값을 초과하여 커질 수있는 방법에 대해 당황 스럽습니다.

+0

Jave에서 .remove (0)을 수행하면 자동으로 나머지 항목이 아래로 이동합니까? –

+0

javadoc에 따르면 ... – assylias

+0

지도를 제거한 후 크기를 다시 기록하면 가치가있는 항목이 실제로 제거되었는지 확인할 수 있습니다. – assylias

답변

2

몇 가지 문제가 있습니다.

우선, cachedBitmapUrlsOrderList입니다. 동일한 비트 맵이 두 번 이상 요청되면 어떻게됩니까? 목록에 전체 URL이 중복됩니다. 따라서 처음으로 한도에 도달하면 목록과지도에서 URL을 삭제합니다. 그러나 동일한 URL이 여전히 목록에 있으며 일치하는지도 항목이입니다. 따라서 목록에서 동일한 URL을 제거하려는 시도가 이 아니고이지도에서 아무 것도 제거하면지도가 커집니다.

addBitmapToCache()의 시작 부분에서 URL이 이미 캐시 된 경우 bitmapCache.containsKey(url)으로 확인하면이 문제를 방지 할 수 있습니다. 그렇다면 맵을 수정할 필요가 없습니다. 이 항목이 가장 최근 항목으로 기억되는지 확인하십시오.

또는 목록을 고유 한 모음 값으로 변경하십시오. 아마도 타임 스탬프에 대한 URL 맵 또는 Set. (내가 결정하도록하겠습니다.)

또한 get()size() 메서드도 동기화되어야합니다.

그리고 get()은 검색된 항목의 타임 스탬프를 업데이트해야 최신 항목이됩니다.

+1

성장 추세에 동의하지만 map.containsKey (URL)을 확인하는 캐시 추가 메소드의 시작 부분에 줄을 추가하는 것이 가장 쉽지는 않습니까? –

+0

훌륭하게, 정말 고마워! 총체적인 의미를가집니다. –

+0

@ cotton.m 네, 제 답변에 추가했습니다. 감사. –

2

그래함의 대답에 따라 clearCache으로 전화하면 cachedBitmapUrlsOrder이 삭제되지 않습니다. 다음 번에 한도에 도달하면 아무 것도 제거하지 않을 것입니다.

String oldestUrl = cachedBitmapUrlsOrder.remove(0); 
bitmapCache.remove(oldestUrl); // bitmapCache does not have such key 
+0

또 하나의 큰 잡기. 필자는 나를 위해 Developer 101로 돌아 간다. –

관련 문제