Кэш ExpiringMap или TTL
http://www.java2s.com/Code/Java/Collections-Data-Structure/ExpiringMap.htm
Q1) Я смотрел на приведенный выше код кэширования. Я запутался, зачем нам нужна блокировка при вызове getLastAccessTime. Этот метод вызывается только потоком Expirer.
Q2) Допустим, если Map вызывается только потоком, тогда нам когда-нибудь понадобится блокировка повторного входа в ExpiringObject. Поскольку setLastAccessTime вызывается только потоком при вызове метода put Map, а метод getLastAccessTime будет вызываться потоком Expirer. Причина, по которой я спрашиваю, заключается в том, что я протестировал вставку объектов размером 1M, Reentrant Lock занимает более 100 МБ
2 ответа
Блокировка необходима, поскольку длинное значение не может быть обновлено атомарно в 32-битных системах.
Альтернативы:
Замените длинный на длинный. Ссылка обновлена атомарно.
Используйте AtomicLong
Продолжайте использовать объект Lock, но используйте статический массив блокировок размером примерно с двойным числом доступных процессоров и индексируйте его с помощью блокировок [hashCode() % locks.length]
И последний вариант: используйте кеш, который уже оптимизирован, например, EHCache, Google Guava или cache2k.
Чтобы ответить на ваш вопрос, я не совсем уверен, почему lastAccessTimeLock
потребует блокировки, поскольку изменения в ней не должны совпадать с изменениями чего-либо еще (атомарно). ИМО, замок не нужен. Вы хотели бы убедиться, что изменения в lastAccessTimeLock
видны другим потокам, хотя, что можно сделать, пометив его как volatile
или используя AtomicLong
,
Что касается вашей проблемы использования памяти, вы можете проверить эту библиотеку ExpiringMap, а не использовать реализацию Mina.