逐咖啡因驱逐似乎无效

我正在使用咖啡因缓存。

我想将其置于尺寸限制下,但无法正常工作。

测试1:

Cache<String,String> cache = caffeine.newBuilder()
                .maximumSize(3)
                .build();

        Cache<String,String> cache = caffeine.newBuilder()
                .maximumSize(3)
                .build();

        for (int i = 1; i <= 10; i ++) {
            String val = String.valueOf(i);
            cache.put(val,val);
        }

        System.out.println("cache size: " + cache.estimatedSize() + ",cache keys: " + cache.asMap().values().stream().collect(Collectors.joining(",")));


result:   cache size: 10,cache keys: 1,2,10

另一个测试:尝试获取密钥并将max设置为1

Cache<String,String> cache = caffeine.newBuilder()
                .maximumSize(1)
                .build();

        for (int i = 1; i <= 10; i ++) {
            String val = String.valueOf(i);
            cache.put(val,val);

            if (i % 2 == 0) {
                cache.getIfPresent("5");
            }
        }

        System.out.println("cache size: " + cache.estimatedSize() + ",")));


cache size: 10,cache keys: 2,3,4,5,6,7,8,9,10

最后一次测试:运行100次,最大大小为1

 Cache<String,String> cache = caffeine.newBuilder()
                .maximumSize(1)
                .build();

        for (int i = 1; i <= 100; i ++) {
            String val = String.valueOf(i);
            cache.put(val,")));

cache size: 99,cache keys: 96,97,99,19,23,58

有人可以帮助我理解这一点以及如何使其正常工作吗?


感谢Ben Manes,我添加了.executor(Runnable::run)

现在执行此操作后,我只会得到3项

 Cache<String,String> cache = caffeine.newBuilder()
                .maximumSize(3)
                .executor(Runnable::run)
                .build();

        for (int i = 1; i <= 10; i ++) {
            String val = String.valueOf(i);
            cache.put(val,val);

            if (i % 2 == 0) {
                cache.getIfPresent("5");
            }
        }
        cache.cleanUp();
        System.out.println("cache size: " + cache.estimatedSize() + ",cache: " + CodecUtils.toJson(cache.asMap().values()));


cache size: 3,cache: ["3","9","10"]

  1. 这不会阻塞我的线程吗?
  2. 为什么多次使用时键5都不在缓存中?
xzsytc 回答:逐咖啡因驱逐似乎无效

默认情况下,缓存将异步执行某些操作,例如逐出并通知删除侦听器。这是为了最大程度地减少请求等待时间,因为请求本身不需要辅助工作,并且用户提供的回调可能很昂贵。

缓存本身的维护工作非常便宜,因此,如果需要,可以使用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,5=5}
6 -> {2=2,6=6}
7 -> {2=2,7=7}
8 -> {2=2,8=8}
9 -> {2=2,9=9}
10 -> {2=2,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,5=5}
6 -> {3=3,5=5,6=6}
7 -> {3=3,7=7}
8 -> {3=3,8=8}
9 -> {3=3,9=9}
10 -> {3=3,10=10}
cache size: 3
本文链接:https://www.f2er.com/2378089.html

大家都在问