Comprehensive Guide to Using Caffeine Cache in Java

This article provides an in‑depth tutorial on configuring and using the Caffeine caching library in Java, covering cache creation, property settings such as initial capacity, maximum size, weight, expiration policies, statistics collection, custom listeners, and advanced features like removal listeners and cache writers.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Comprehensive Guide to Using Caffeine Cache in Java

Conclusion: Caffeine is currently the best‑performing local cache, so choose it directly when a local cache is needed.

First, see a small example to understand how to create a Caffeine cache instance.

Caffeine caffeine = Caffeine.newBuilder()
        .initialCapacity(3)
        .maximumSize(4);
Cache cache = caffeine.build();
cache.put("aa", 13);
System.out.println(cache.getIfPresent("aa"));

Caffeine acts as a cache factory that can create multiple Cache instances, each inheriting the configuration set on the Caffeine builder.

1. Cache Properties

1.1 Initial Capacity

initialCapacity : integer indicating how many entries the cache can initially hold.

Setting this avoids repeated resizing when the expected size is known.

1.2 Maximum Size and Maximum Weight

maximumSize : the maximum number of entries; exceeding this triggers an asynchronous eviction thread.

Note: If maximum size is 2 and a third entry is added, the eviction thread runs, but until it finishes, three entries may be present.

maximumWeight : total weight limit; each entry must have a weight, and eviction occurs when the sum exceeds the limit.

class Person {
        Integer age;
        String name;
}
Caffeine<String, Person> caffeine = Caffeine.newBuilder()
        .maximumWeight(30)
        .weigher((String key, Person value) -> value.getAge());
Cache<String, Person> cache = caffeine.build();
cache.put("one", new Person(12, "one"));
cache.put("two", new Person(18, "two"));
cache.put("three", new Person(1, "three"));
Thread.sleep(10);
System.out.println(cache.estimatedSize());
System.out.println(cache.getIfPresent("two"));

Only one of maximum size or maximum weight can be used to limit cache space.

1.3 Cache Statistics

CacheStats records metrics such as totalLoadTime, loadFailureRate, averageLoadPenalty, evictionCount, hitCount, missCount, requestCount, etc.

CacheStats.minus(@Nonnull CacheStats other)
CacheStats.plus(@Nonnull CacheStats other)

Example of retrieving stats:

Caffeine<String, Person> caffeine = Caffeine.newBuilder()
        .maximumWeight(30)
        .recordStats()
        .weigher((String key, Person value) -> value.getAge());
Cache<String, Person> cache = caffeine.build();
cache.put("one", new Person(12, "one"));
cache.put("two", new Person(18, "two"));
CacheStats stats = cache.stats();
System.out.println(stats.hitCount());

1.4 Custom Stats Counter

Implement the StatsCounter interface to handle hits, misses, load successes/failures, and evictions.

public class MyStatsCounter implements StatsCounter {
    @Override
    public void recordHits(int i) { System.out.println("命中次数:" + i); }
    @Override
    public void recordMisses(int i) { System.out.println("未命中次数:" + i); }
    @Override
    public void recordLoadSuccess(long l) { System.out.println("加载成功次数:" + l); }
    @Override
    public void recordLoadFailure(long l) { System.out.println("加载失败次数:" + l); }
    @Override
    public void recordEviction() { System.out.println("因为缓存大小限制,执行了一次缓存清除工作"); }
    @Override
    public void recordEviction(int weight) { System.out.println("因为缓存权重限制,执行了一次缓存清除工作,清除的数据的权重为:" + weight); }
    @Override
    public CacheStats snapshot() { return null; }
}

1.5 Thread Pool

Caffeine uses ForkJoinPool.commonPool() by default for asynchronous tasks; a custom executor can be set via executor() if needed.

1.6 Expiration Policies

expireAfterAccess : entry expires after a period of inactivity (read or write).

Caffeine<String, Person> caffeine = Caffeine.newBuilder()
        .maximumWeight(30)
        .expireAfterAccess(2, TimeUnit.SECONDS)
        .weigher((String key, Person value) -> value.getAge());
Cache<String, Person> cache = caffeine.build();
cache.put("one", new Person(12, "one"));
cache.put("two", new Person(18, "two"));
Thread.sleep(3000);
System.out.println(cache.getIfPresent("one"));
System.out.println(cache.getIfPresent("two"));

expireAfterWrite : entry expires a fixed time after the last write.

Caffeine<String, Person> caffeine = Caffeine.newBuilder()
        .maximumWeight(30)
        .expireAfterWrite(2, TimeUnit.SECONDS)
        .weigher((String key, Person value) -> value.getAge());
Cache<String, Person> cache = caffeine.build();
cache.put("one", new Person(12, "one"));
cache.put("two", new Person(18, "two"));
Thread.sleep(1000);
System.out.println(cache.getIfPresent("one").getName());
Thread.sleep(2000);
System.out.println(cache.getIfPresent("one"));

expireAfter : custom Expiry implementation allowing different expiration times for create, update, and read events.

1.7 Refresh After Write

Delays refreshing cached data for LoadingCache and AsyncLoadingCache using refreshAfterWrite(duration, unit).

1.8 Removal Listener

Asynchronous listener triggered on entry removal or replacement, providing key, value, and cause.

MyStatsCounter myStatsCounter = new MyStatsCounter();
Caffeine<String, Person> caffeine = Caffeine.newBuilder()
        .maximumWeight(30)
        .removalListener((String key, Person value, RemovalCause cause) -> {
            System.out.println("被清除人的年龄:" + value.getAge() + ";  清除的原因是:" + cause);
        })
        .weigher((String key, Person value) -> value.getAge());
Cache<String, Person> cache = caffeine.build();
cache.put("one", new Person(12, "one"));
cache.invalidate("one");

1.9 Weak and Soft References

Cache can use weakKeys(), weakValues(), or softValues() to allow garbage collection of keys/values.

1.10 Synchronous Writer

Implement CacheWriter to receive synchronous callbacks on write and delete operations.

public class MyCacheWriter implements CacheWriter<String, Application.Person> {
    @Override
    public void write(String s, Application.Person person) {
        System.out.println("新增/更新了一个新数据:" + person.getName());
    }
    @Override
    public void delete(String s, Application.Person person, RemovalCause removalCause) {
        System.out.println("删除了一个数据:" + person.getName());
    }
}

2. Cache Operations

V getIfPresent(K key)

: returns value or null. void put(K key, V value): stores a key‑value pair. Map<K,V> getAllPresent(Iterable<?> keys): bulk read. void putAll(Map<? extends K, ? extends V> map): bulk write. void invalidate(K key): removes a single entry. void invalidateAll(): clears the cache. long estimatedSize(): number of entries. CacheStats stats(): retrieves metrics. ConcurrentMap<K,V> asMap(): view as a map. void cleanUp(): performs maintenance and eviction.

V get(K key, Function<? super K, ? extends V> mappingFunction)

: loads value if absent.

Caffeine<String, Person> caffeine = Caffeine.newBuilder()
        .maximumWeight(30)
        .weigher((String key, Person value) -> value.getAge());
Cache<String, Person> cache = caffeine.build();
cache.put("one", new Person(12, "one"));
cache.get("hello", k -> new Person(13, k));
System.out.println(cache.getIfPresent("hello").getName());

Source: blog.csdn.net/dgh112233/article/details/118915259

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendperformanceCacheCaffeine
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.