По умолчанию кэш будет выполнять некоторые операции асинхронно, например, выселение и уведомление слушателя удаления. Это сводит к минимуму задержки запроса, поскольку вспомогательная работа не является необходимой для самого запроса, а предоставляемые пользователем обратные вызовы могут быть дорогими.
Собственные работы по обслуживанию кэша очень дешевы, поэтому вы можете безопасно запустить их на поток звонящего по желанию с помощью Caffeine.executor(Runnable::run)
. Это накажет вызывающего абонента дополнительным удалением записи, но не заблокирует выполнение других операций. Это связано с тем, что кэш-память внутренне использует несколько блокировок и рабочих буферов, поэтому он может планировать работу, когда блокировка занята, а не потоками блоков.
Что касается размера, то это потому, что запись исключена ранее чтобы быть извлеченным, чтобы он не наращивал частоту. getIfPresent
не увеличивает частоту, если запись отсутствует, тогда как get(key, /* loading function */)
- потому что штрафуется за загрузку значения в промах. Политика выселения использует в своих решениях как актуальность, так и частоту, поэтому она может высвобождать недавние поступления как можно раньше, как «чудеса одного удара», то есть загрязнение кэша.
Если мы возьмем ваш код как есть и выведем состояние кэша мы видим это,
for (int i = 1; i <= 10; i++) {
String val = String.valueOf(i);
cache.put(val, val);
System.out.println(val + " -> " + cache.asMap());
if (i % 2 == 0) {
cache.getIfPresent("5");
}
}
cache.cleanUp();
System.out.println("cache size: " + cache.estimatedSize());
1 -> {1=1}
2 -> {1=1, 2=2}
3 -> {1=1, 2=2, 3=3}
4 -> {2=2, 3=3, 4=4}
5 -> {2=2, 3=3, 5=5}
6 -> {2=2, 3=3, 6=6}
7 -> {2=2, 3=3, 7=7}
8 -> {2=2, 3=3, 8=8}
9 -> {2=2, 3=3, 9=9}
10 -> {2=2, 3=3, 10=10}
cache size: 3
Если мы обращаемся к ключу 5
на каждой итерации, то он сохраняется,
for (int i = 1; i <= 10; i++) {
String val = String.valueOf(i);
cache.put(val, val);
System.out.println(val + " -> " + cache.asMap());
cache.getIfPresent("5");
}
cache.cleanUp();
System.out.println("cache size: " + cache.estimatedSize());
1 -> {1=1}
2 -> {1=1, 2=2}
3 -> {1=1, 2=2, 3=3}
4 -> {2=2, 3=3, 4=4}
5 -> {2=2, 3=3, 5=5}
6 -> {3=3, 5=5, 6=6}
7 -> {3=3, 5=5, 7=7}
8 -> {3=3, 5=5, 8=8}
9 -> {3=3, 5=5, 9=9}
10 -> {3=3, 5=5, 10=10}
cache size: 3