Guava缓存及Guava线程池

Guava缓存

Guava缓存是Google Guava库中提供的一种缓存实现,可以帮助我们在应用程序中轻松实现缓存功能。Guava缓存提供了一些高级功能,例如自动加载、过期时间、最大缓存大小、缓存回收等。

CacheBuilder跟Guava缓存的关系

CacheBuilder是Guava缓存的构建器,提供了一些方法来配置缓存的行为,例如设置缓存的最大大小、过期时间、缓存回收策略等。通过CacheBuilder,可以创建一个Guava缓存实例。

即CacheBuilder是Guava缓存的一部分,提供了一种方便的方式来创建和配置Guava缓存实例。

CacheBuilder类的常用方法

maximumSize(int size)

作用:设置缓存的最大容量,当超过这个容量的时候,最近最少使用的条目会被回收。

java 复制代码
Cache<String, String> cache = CacheBuilder.newBuilder()
        .maximumSize(100)
        .build();
        

maximumWeight(long weight)

作用:设置缓存的最大重量,当超过这个重量的时候,最近最少使用的条目会被回收。

java 复制代码
Cache<String, String> cache = CacheBuilder.newBuilder()
        .maximumWeight(1000)
        .build();
        

expireAfterAccess(long duration, TimeUnit unit)

作用:在指定时间内没有被读/写访问,则回收缓存条目。

java 复制代码
Cache<String, String> cache = CacheBuilder.newBuilder()
        .expireAfterAccess(10, TimeUnit.MINUTES)
        .build();
        

expireAfterWrite(long duration, TimeUnit unit)

作用:在指定时间内没有被写访问,则回收缓存条目。

java 复制代码
Cache<String, String> cache = CacheBuilder.newBuilder()
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .build();
        

refreshAfterWrite(long duration, TimeUnit unit)

作用:设置缓存项在写入一定时间后自动刷新。

java 复制代码
Cache<String, String> cache = CacheBuilder.newBuilder()
        .refreshAfterWrite(10, TimeUnit.MINUTES)
        .build();
        

initialCapacity(int capacity)

作用:设置缓存的初始容量,用于控制缓存的内存分配。

java 复制代码
Cache<String, String> cache = CacheBuilder.newBuilder()
        .initialCapacity(100)
        .build();

recordStats()

作用:启用缓存统计信息,可以获取缓存的命中率、平均加载时间等指标。

java 复制代码
Cache<String, String> cache = CacheBuilder.newBuilder()
        .recordStats()
        .build();

build()

作用:构建缓存实例。

java 复制代码
Cache<String, String> cache = CacheBuilder.newBuilder()
        .maximumSize(100)
        .build();

build方法用于构建一个缓存对象。接受一个CacheLoader对象作为参数,用于定义缓存的加载逻辑。CacheLoader是一个抽象类,需要实现load方法来定义如何加载缓存数据。

build方法定义:

java 复制代码
public <K, V> Cache<K, V> build(CacheLoader<? super K, V> loader)

该方法返回一个Cache对象,该对象可以用于存储和获取缓存数据

示例代码:

java 复制代码
  public void test() {
        // 创建一个Cache对象
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100) // 设置缓存的最大容量
                .expireAfterWrite(10, TimeUnit.MINUTES) // 设置缓存项的过期时间
                .build(new CacheLoader<String, String>() {
                    @Override
		            public String load(String key) throws Exception {
		                // 在缓存中没有找到对应值时,自动加载该值
		                return "value for " + key;
		            }
                });

        try {
            // 获取缓存数据
            String value = cache.get("key");
            System.out.println(value); // 输出:Value for key

            // 缓存中不存在该数据时,会调用CacheLoader的load方法加载数据
            String value2 = cache.get("key2");
            System.out.println(value2); // 输出:Value for key2
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

创建了一个最大容量为100,写入后10分钟过期的缓存实例,并使用CacheLoader自动加载缓存值。当缓存中没有找到对应值时,CacheLoader的load方法会被调用,返回对应的值。

CacheLoader类

CacheLoader类是Guava缓存库中的一个重要类,用于定义缓存加载的逻辑。

CacheLoader类的常用方法

load(K key)

作用:加载指定键的缓存值。如果缓存中不存在该键的值,则通过该方法加载并返回

  • 当缓存中不存在指定键的值时,会调用该方法。
  • 该方法用于从数据源或其他方式获取缓存的值。

loadAll(Iterable<? extends K> keys)

作用:批量加载指定键集合的缓存值。如果缓存中不存在某个键的值,则通过该方法加载

java 复制代码
acheLoader<String, String> cacheLoader = new CacheLoader<String, String>() {
    @Override
    public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception {
        Map<String, String> values = new HashMap<>();
        for (String key : keys) {
            // 从数据库或其他数据源加载缓存值的逻辑
            values.put(key, "Value for " + key);
        }
        return values;
    }
};

List<String> keys = Arrays.asList("key1", "key2", "key3");
Map<String, String> values = cacheLoader.loadAll(keys);
System.out.println(values); // Output: {key1=Value for key1, key2=Value for key2, key3=Value for key3}

reload(K key, V oldValue)

作用:重新加载指定键的缓存值。该方法在缓存值过期或被移除时调用,用于更新缓存值

  • 当缓存中的键值对需要被刷新或重新加载时,会调用该方法。
  • 该方法在缓存中存在旧值的情况下被调用,用于获取新值并替换旧值。
  • 通常在缓存的刷新策略中使用,例如定时刷新或手动刷新。
java 复制代码
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class MyCacheLoader<K, V> extends CacheLoader<K, V> {
    private Executor executor = Executors.newSingleThreadExecutor();

    @Override
    public V load(K key) throws Exception {
        // 在这里实现加载缓存的逻辑
        // 返回缓存值
        return null;
    }

    @Override
    public ListenableFuture<V> reload(K key, V oldValue) throws Exception {
        SettableFuture<V> future = SettableFuture.create();

        executor.execute(() -> {
            try {
                // 在这里实现重新加载缓存的逻辑
                // 将重新加载的缓存值设置到future中
                V newValue = null;
                future.set(newValue);
            } catch (Exception e) {
                // 如果重新加载缓存失败,设置异常到future中
                future.setException(e);
            }
        });

        return future;
    }
}

创建了一个自定义的CacheLoader类,继承自CacheLoader<K, V>。在load方法中,你可以实现加载缓存的逻辑,并返回缓存值。

在reload方法中,使用了ListenableFuture来表示重新加载缓存的异步操作。创建了一个SettableFuture对象,用于保存重新加载的缓存值。然后,使用一个Executor来执行重新加载缓存的逻辑,将重新加载的缓存值设置到future中。如果重新加载缓存失败,我们将异常设置到future中。

这样,就可以在CacheLoader类中使用reload方法来实现缓存的重新加载操作了。

Guava线程池

Guava的线程池主要包含以下几个类:

  1. ListeningExecutorService:一个可监听的ExecutorService,可以在任务执行完成时触发回调函数。

  2. MoreExecutors:提供了一些常用的ExecutorService的工厂方法,例如newDirectExecutorService()、newFixedThreadPool()、newCachedThreadPool()等。

  3. ThreadFactoryBuilder:一个用于创建线程工厂的Builder类,可以设置线程名、优先级、是否为守护线程等属性。

java 复制代码
import com.google.common.util.concurrent.*;

import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

public class GuavaThreadPoolDemo {

    public static void main(String[] args) throws Exception {
        // 创建线程池
        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
                Executors.newFixedThreadPool(10, new ThreadFactoryBuilder()
                        .setNameFormat("guava-pool-%d")
                        .setDaemon(true)
                        .build()));

        // 提交任务
        ListenableFuture<String> future = executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                // 模拟耗时操作
                Thread.sleep(1000);
                return "Hello, Guava!";
            }
        });

        // 添加回调函数
        Futures.addCallback(future, new FutureCallback<String>() {
            @Override
            public void onSuccess(String result) {
                System.out.println(result);
            }

            @Override
            public void onFailure(Throwable t) {
                t.printStackTrace();
            }
        }, executorService);

        // 关闭线程池
        executorService.shutdown();
    }
}

使用MoreExecutors工厂方法创建了一个固定大小的线程池,然后使用ListeningExecutorService包装它,使其可以监听任务执行完成事件。接着,提交了一个Callable任务,并使用Futures.addCallback方法添加了一个回调函数,当任务执行完成时会自动触发回调函数。最后,关闭了线程池。

Guava的线程池和Guava缓存的结合示例代码

java 复制代码
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class MyCacheLoader<K, V> extends CacheLoader<K, V> {
    // 创建线程池
    ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
            Executors.newFixedThreadPool(10, new ThreadFactoryBuilder()
                    .setNameFormat("guava-pool-%d")
                    .setDaemon(true)
                    .build()));

    @Override
    public V load(K key) throws Exception {
        // 在这里实现加载缓存的逻辑
        // 返回缓存值
        return null;
    }

    @Override
    public ListenableFuture<V> reload(K key, V oldValue) throws Exception {
        SettableFuture<V> future = SettableFuture.create();

        executorService.execute(() -> {
            try {
                // 在这里实现重新加载缓存的逻辑
                // 将重新加载的缓存值设置到future中
                V newValue = null;
                future.set(newValue);
            } catch (Exception e) {
                // 如果重新加载缓存失败,设置异常到future中
                future.setException(e);
            }
        });

        return future;
    }
}
相关推荐
2401_857600951 小时前
深入剖析:Spring MVC与Struts的较量
struts·spring·mvc
被猫枕的咸鱼1 小时前
springmvc通过使用map来进行数据的接收和使用
spring
荆州克莱2 小时前
Big Data for AI实践:面向AI大模型开发和应用的大规模数据处理套件
spring boot·spring·spring cloud·css3·技术
只是有点小怂2 小时前
受害者缓存(Victim Cache)
缓存
酸奶代码4 小时前
Spring AOP技术
java·后端·spring
simpleGq4 小时前
Redis知识点整理 - 脑图
数据库·redis·缓存
代码小鑫4 小时前
A034-基于Spring Boot的供应商管理系统的设计与实现
java·开发语言·spring boot·后端·spring·毕业设计
.生产的驴5 小时前
SpringCloud Gateway网关路由配置 接口统一 登录验证 权限校验 路由属性
java·spring boot·后端·spring·spring cloud·gateway·rabbitmq
运维小文5 小时前
服务器硬件介绍
运维·服务器·计算机网络·缓存·硬件架构
提高记忆力5 小时前
SpringBoot整合FreeMarker生成word表格文件
java·spring