SoFunction
Updated on 2025-03-08

Summary of Java guava framework LoadingCache and CacheBuilder local small-capacity cache framework

Introduction to Guava Cache Local Cache Framework

It is mainly a kind of cache local data into memory, but the amount of data cannot be too large, otherwise it will occupy too much memory. Although the framework itself has done considerable data recycling, it cannot be abused. It needs to meet the following advantages scenarios to be suitable for use. The speed of accessing memory is faster than that of redis and other databases.

Some and demand scenarios:

  • Very high performance requirements
  • Willing to consume some memory space to increase speed
  • It is expected that some keys will be queried multiple times
  • The total amount of data stored in the cache will not exceed the memory capacity

keyThe points are:There is frequently accessed data, and the data itself consumes very little memory, store this data into the cache framework to manage it to provide performance

Advantages provided

  • The cache can set the expiration time and provide an elimination mechanism when there is too much data.
  • It is thread-safe and supports concurrent read and write
  • When the cache cannot be retrieved, it can be obtained from the data source and added to the cache. GuavaCache can be controlled by using the load method of the CacheLoader. For the same key, only one request is allowed to read the source and backfill the cache, and other requests are blocked and waited.
  • You can view cached loading information, etc.

Usage and method

Maven dependencies:

        <dependency>
            <groupId></groupId>
            <artifactId>guava</artifactId>
            <version>20.0</version>
        </dependency>

The easiest build case

Cache<String, Object> cache = ().build();
("aaa", 156484);

andMapSimilarly, use when obtainingget()The method can obtain the data placed in it.

passCacheBuildercreateCacheObjects, which store a chained construct similar to Map build method, similar to the builder builder pattern, return all are the current object itself, and end the construction after calling the build method.

Some construction parameter methods after () are introduced:

initialCapacity: The initial data capacity of the cache is generally appropriate to the actual situation, otherwise it will cause waste of resources.
maximumSize: The cache can contain the maximum number of entry. After the number limit exceeds the number limit, the entry will be eliminated. When it is close to the maximum, it will eliminate infrequently used data. When set to 0, it is a scenario where no cache is used to test data loading.

Expiry time setting

expireAfterAccess: How long after the data is written, the accessed object has not been accessed is considered expired
expireAfterWrite: After the data is written to the cache, it has not been updated for a long time and then expires.

It can be written as follows:

        Cache<String, Object> cache = ()
                .initialCapacity(5)
                .maximumSize(10)
                .expireAfterWrite(10, ).build();
		("154", "djawbdawd");

The expiration time unit is controlled by TimeUnit, both time, minute and second

WeakKeys, weakValues, softValues)

weakKeys
Set the cached key to weakKey mode.
By default, "strong relationships" are used to save the key value. When set to weakKey, "==" is used to match the key value. In case of weakKey, the data may be GC. After the data is GC, it may still be counted by the size method, but executing the read or write method on it is no longer effective.

weakValues
Set the cached data to weakValues ​​mode.
When enabled, some data will be GC. By default, "strong relationship" is used to save the key value. When set to weakValue, "==" is used to match the value value. After the data is GC, it may still be counted by the size method, but executing the read or write method on it is no longer effective.

softValues
Set the cached data to softValues ​​mode.
When enabled, all data is wrapped with the SoftReference class (that is, to store the real data in the SoftReference instance). Data wrapped with SoftReference will be hosted by the global garbage collection manager and GC data periodically according to the LRU principle. After the data is GC, it may still be counted by the size method, but executing the read or write method on it is no longer effective.

These are also()Set afterward.

Actively delete data

When creating an object through builder is completed, the data can be cleared in the following ways:
invalidateAll: Clear all data, enter the parameter as Iterable type parameter, that isGeneral List collectionThat's right, the content is all keys
invalidate: Single delete, enter the parameter as key

Delete the listener

That is, it is used to monitor the data in the cache, which will be triggered when the data is deleted.
Similar to the following code:

        RemovalListener&lt;String, String&gt; listener = new RemovalListener&lt;String, Object&gt;() {
            public void onRemoval(RemovalNotification&lt;String, String&gt; notification) {
            // (); // The key of the currently deleted object            // (); // The value of the currently deleted object            }
        };
        Cache&lt;String, Object&gt; cache = ()
                .maximumSize(5)
                // Add and remove listener                .removalListener(listener) 
                .build();

It is worth noting that deletion here is not only an active deletion, but also considered to be a deletion when the capacity limit is reached or expires or the data disappears due to other policies.

Generally, cache actively loads data

That is, when the value corresponding to the specified key cannot be obtained in the cache, you need to take the initiative to obtain it in other ways:

The writing method is similar to the following, and you need to provide the implementation method of obtaining:

Cache&lt;String, Object&gt; cache = ()
                .initialCapacity(5)
                .maximumSize(10)
                .expireAfterWrite(10, ).build();
        ("154", "djawbdawd");
        try {
            ("aaa", new Callable&lt;Object&gt;() {
                @Override
                public Object call() throws Exception {
                    // How to get it                    // The return value of the method is the value corresponding to the current key and will be added to the cache                    return null;
                }
            });
        } catch (ExecutionException e) {
            ();
        }

The method needs to be rewrite to obtain the actual data in the method within the Callable. The return value of the method is the value corresponding to the current key and will be added to the cache.If multiple threads exist at the same time, the same non-existent key is obtained., then only one will be executed and the others will need to wait. And after one thread obtains it, other threads will also be able to obtain the data.

Statistical information

When creating a cache object, the statistics will be enabled and you can pass()Get cache
For example:

        Cache<String, Object> cache = ()
                .initialCapacity(5)
                .maximumSize(10)
                .recordStats()
                .expireAfterWrite(10, ).build();
        ("154", "djawbdawd");
        try {
            ("aaa", new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    // .......
                    return null;
                }
            });
        } catch (ExecutionException e) {
            ();
        }
        ();

The most commonly used LoadingCache

LoadingCache is a subinterface of Cache. Compared with Cache, when reading a record of a specified key from LoadingCache, if the record does not exist, LoadingCache can automatically perform the operation of loading data to the cache, and the loading method needs to be rewrite when defining.
The definition of the LoadingCache interface is as follows:

CacheLoader&lt;String, String&gt; loader = new CacheLoader&lt;&gt;() {
		// Method to load data that does not exist            public String load(String key) throws Exception {
            // .............
                return null;
            }
        };
        LoadingCache&lt;String, String&gt; loadingCache = ()
                .maximumSize(5)
                .build(loader);

Or as follows:

LoadingCache&lt;String, Object&gt; infoItemCache = ()
		.initialCapacity(5)
		.maximumSize(10)
		.expireAfterAccess(3, ).build(new CacheLoader&lt;String, Object&gt;() {
                    // Rewrite the loading method using LoadingCache. After rewriting, the rewritten load method will be executed when the value corresponding to the key cannot be obtained from the cache, and the return value will become the value corresponding to the parameter key and be stored                    @Override
                    public Object load(String s) throws Exception {
                        // ............
                        return null;
                    }
                });

Simple tools can be customized as follows:

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class MyCache {
    /**
      * Initialize cache capacity size
      */
    private static final int INITIAL_CAPACITY = 5;
    /**
      * The cache can contain the maximum number of entry. After the number limit exceeds the number limit, the entry will be eliminated. When it is close to the maximum, it will be a scenario where no cache is used. It is used to test data loading.
      */
    private static final long MAXIMUM_SIZE = 10;
    /**
      * After being placed in cache, it will expire if it is not accessed within the specified time.
      */
    private static final long EXPIRE_AFTER_ACCESS = 5;
    /**
      * cache subinterface, cache object
      */
    private static LoadingCache&lt;String, Object&gt; infoItemCache;
    // Initialize cache objects    static {
        infoItemCache = ().initialCapacity(INITIAL_CAPACITY).maximumSize(MAXIMUM_SIZE)
                .expireAfterAccess(EXPIRE_AFTER_ACCESS, ).build(new CacheLoader&lt;String, Object&gt;() {
                    // Rewrite the loading method using LoadingCache. After rewriting, the rewritten load method will be executed when the value corresponding to the key cannot be obtained from the cache, and the return value will become the value corresponding to the parameter key and be stored                    @Override
                    public Object load(String s) throws Exception {
                        // ...............
                        return null;
                    }
                });
    }
    /**
      * Get data from cache, if it does not exist, re-query
      * @return
      */
    public static Object getFromCache(String key) throws ExecutionException {
        Object data = (key);
        return data;
    }
}

If you need to obtain the Bean service from Spring, you can obtain it through Spring's applicationConext

This is the article about Java guava framework LoadingCache, CacheBuilder Local small-capacity cache framework learning and summary. For more related Java guava framework LoadingCache content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!