Какую коллекцию Java следует использовать для реализации поточно-ориентированного кэша? - PullRequest
10 голосов
/ 28 июля 2010

Я пытаюсь реализовать простой кеш, не делая слишком много работы (естественно).Мне кажется, что одной из стандартных коллекций Java должно быть достаточно, с небольшой дополнительной работой.В частности, я храню ответы от сервера, и ключи могут быть либо строкой URL запроса, либо хеш-кодом, сгенерированным из URL., но похоже, что этот метод заставляет меня управлять тем, какие объекты я хочу сохранить, и любые объекты, которыми я не управляю с помощью сильных ссылок, немедленно удаляются.Стоит ли вместо этого попробовать значения ConcurrentHashMap из SoftReference?Или они тоже будут убраны довольно агрессивно?

Я сейчас смотрю на класс LinkedHashMap.С некоторыми изменениями это выглядит многообещающе для кэша MRU.Любые другие предложения?

Какой бы коллекцией я ни пользовался, я должен попытаться вручную удалить значения LRU или могу ли я доверять виртуальной машине смещение против восстановления недавно использованных объектов?разработка на Android, поэтому я бы предпочел не импортировать сторонние библиотеки.Я имею дело с очень маленькой кучей (от 16 до 24 МБ), поэтому виртуальная машина, вероятно, очень хочет вернуть ресурсы.Я предполагаю, что GC будет агрессивным.

Ответы [ 5 ]

6 голосов
/ 28 июля 2010

Если вы используете ключи SoftReference, виртуальная машина будет (сильно) смещена по отношению к недавно полученным объектам. Однако было бы довольно трудно определить семантику кэширования - единственная гарантия, которую SoftReference дает вам (через WeakReference), состоит в том, что будет очищено до того, как будет выдан OutOfMemoryError. Для реализации JVM было бы совершенно законно обрабатывать их идентично WeakReferences, после чего вы можете получить кеш, который ничего не кеширует.

Я не знаю, как все работает на Android, но с недавними JVM от Sun можно настроить поведение SoftReference с помощью параметра командной строки -XX: SoftRefLRUPolicyMSPerMB, который определяет количество миллисекунд, в течение которых объект с мягкой доступностью будет сохраняется на МБ свободной памяти в куче. Как вы можете видеть, это будет исключительно трудно получить предсказуемое поведение продолжительности жизни, с добавленной болью, что этот параметр является глобальным для всех мягких ссылок в ВМ и не может быть настроен отдельно для использования отдельными классами SoftReferences (при каждом использовании могут потребоваться разные параметры).


Самый простой способ создать кэш LRU - расширить LinkedHashMap , как описано здесь . Поскольку вам нужна безопасность потоков, самый простой способ расширить это изначально - просто использовать Collections.synchronizedMap в экземпляре этого пользовательского класса для обеспечения безопасного одновременного поведения.

Остерегайтесь преждевременной оптимизации - если вам не нужна очень высокая пропускная способность, теоретически субоптимальные издержки грубой синхронизации вряд ли будут проблемой. И хорошая новость - если профилирование показывает, что вы выполняете слишком медленно из-за сильной конкуренции за блокировку, у вас будет достаточно информации об использовании вашего кэша во время выполнения, чтобы вы могли найти подходящую альтернативу без блокировки (возможно, основанный на ConcurrentHashMap с некоторой ручной обработкой LRU), а не на предположении по его профилю загрузки.

5 голосов
/ 28 июля 2010

LinkedHashMap прост в использовании для кэширования.Это создает кэш MRU размером 10.

private LinkedHashMap<File, ImageIcon> cache = new LinkedHashMap<File, ImageIcon>(10, 0.7f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<File, ImageIcon> eldest) {
        return size() > 10;
    }
};

Я думаю, вы можете создать класс с синхронизированными делегатами для этого LinkedHashMap.Простите, если мое понимание синхронизации неверно.

1 голос
/ 28 июля 2010

Для синхронизации инфраструктура Коллекции предоставляет синхронизированную карту:

Map<V,T> myMap = Collections.synchronizedMap(new HashMap<V, T>());

Затем вы можете обернуть это или обработать логику LRU в объекте кэша.

1 голос
/ 28 июля 2010

www.javolution.org имеет некоторые интересные функции - синхронизированные быстрые коллекции. В вашем случае стоит попробовать, так как он предлагает также некоторые изящные улучшения для небольших устройств, таких как Android.

0 голосов
/ 28 июля 2010

Мне нравятся коллекции Apache Commons LRUMap

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...