Я не знаю EHCache достаточно хорошо, чтобы давать конкретные рекомендации по нему, чтобы решить вашу проблему, поэтому я опишу, что бы я делал без EHCache.
Давайте предположим, что все потоки обращаются к этому кешу с использованием интерфейса Service, называемого FooService, и компонента EJB, называемого SimpleFooService. Служба будет иметь методы, необходимые для получения необходимых данных (которые также кэшируются). Таким образом, вы скрываете тот факт, что он кэшируется из внешнего интерфейса (http запрашивает объекты).
Вместо того, чтобы просто хранить данные для кэширования в свойстве сервиса, мы сделаем для него специальный объект. Давайте назовем это FooCacheManager. Он будет хранить кэш в свойстве в FooCacheManger (скажем, его типа Map). У него будут геттеры, чтобы получить кеш. Он также будет иметь специальный метод reload (), который будет загружать данные из БД (путем вызова служебных методов для получения данных или через DAO) и заменять содержимое кэша (сохраненного в свойстве). .
Хитрость в следующем:
- Объявите свойство кэша в FooCacheManger как AtomicReference (новый объект объявлен в Java 1.5). Это гарантирует безопасность потока, когда вы читаете, а также присваиваете ему. Ваши действия по чтению / записи никогда не будут конфликтовать или считывать половину записанного значения.
- Функция reload () сначала загрузит данные во временную карту, а затем по окончании назначит новую карту свойству, сохраненному в FooCacheManager. Поскольку свойство AtomicReference, присваивание является атомарным, таким образом, оно в основном перелистывает карту в одно мгновение без какой-либо блокировки.
- Внедрение TTL - пусть FooCacheManager реализует интерфейс QuartzJob и делает его эффективно работой с кварцем. В методе execute задания запустите reload (). В Spring XML определите это задание для запуска каждые хх минут (ваш TTL), которое также можно определить в файле свойств, если вы используете PropertyPlaceHolderConfigurer.
Этот метод эффективен, так как читает темы:
- Не блокировать для чтения
- Не вызывается isExpired () при каждом чтении, что составляет 1 Кбит / с.
Также поток записи не блокируется при записи данных.
Если это не понятно, я могу добавить пример кода.