String boot ConcurrentHashMap 自定义本地缓存

5 篇文章 0 订阅
2 篇文章 0 订阅
本文介绍了如何在Java中使用ConcurrentHashMap实现数据缓存,并通过ScheduledThreadPoolExecutor实现缓存的定时过期清理。重点讲解了put方法的不同版本,以及get和clear操作。
摘要由CSDN通过智能技术生成

文章目录


前言

​ 在 Java 中使用本地缓存最简单的方式就是使 HashMap 或者 ConcurrentHashMap,对于只读场景,两者都可以使用,对于缓存更新的场景,可以使用 ConcurrentHashMap 来保证数据的一致性,二者的使用方式非常简单,这里不再赘述。


在这里插入图片描述

使用

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author liuf
 * @time 2021/8/12
 */
@Component
public class CacheMapUtil {
private static final Logger logger = LoggerFactory.getLogger(CacheMapUtil.class);

    /**
     *  每个缓存默认五分钟
     */
    public static int DEFAULT_CACHE_MINUTE = 5;
    /**
     * 时间前缀
     */
    public static String  EXPIRE_THIME = "_expire_time";

    /**
     * 每个缓存生效时间12小时
     */
    public static final int CACHE_HOLD_TIME_12H = 12 * 60;

    /**
     * 每个缓存生效时间24小时
     */
    public static final int CACHE_HOLD_TIME_24H = 24 * 60;

    /**
     * 每个缓存生效时间一年
     */
    public static final int CACHE_HOLD_TIME_1_YEAR = 365 * 24 * 60;

    /**
     * 数据缓存map
     */
    private static Map<String, Object> dataMap = new ConcurrentHashMap<String, Object>(1000,0.75F ,10);
    /**
     * 数据缓存过期map
     */
    private static Map<String, Date> dataExpireMap = new ConcurrentHashMap<String, Date>(1000,0.75F ,10);


    /**
     * 定时任务删除过期的数据
     */
    @PostConstruct
    private void init() {
        logger.warn("定时任务初始化");
        ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(5);
        scheduled.scheduleWithFixedDelay(() -> {
            dataExpireMap.entrySet().forEach( dateEntry ->{
                if (dateEntry.getValue().compareTo(new Date()) < 0) {
                    // 删除过期内容
                    logger.debug(" Key :{},Value:{}",dateEntry.getKey(),get(dateEntry.getKey()));
                    clear(dateEntry.getKey());
                }
            });

        }, 300, 100, TimeUnit.SECONDS);
        //300表示首次执行任务的延迟时间,100表示每次执行任务的间隔时间,TimeUnit.MILLISECONDS执行的时间间隔数值单位

    }


    /**
     * 将一个key、value值放入内存缓存,并设置过期分钟数
     *
     * @param key
     * @param val
     */
    public static void put(String key, Object val) {
        dataMap.put(key, val);
        dataExpireMap.put(key, DateUtil.addMinutes(new Date(), DEFAULT_CACHE_MINUTE));
    }


    /**
     * 将一个key、value值放入内存缓存,并设置过期分钟数
     *
     * @param key
     * @param val
     */
    public static void put12H(String key, Object val) {
        dataMap.put(key, val);
        dataExpireMap.put(key, DateUtil.addMinutes(new Date(), CACHE_HOLD_TIME_12H));
    }

    /**
     * 将一个key、value值放入内存缓存,并设置过期分钟数
     *
     * @param key
     * @param val
     */
    public static void put24H(String key, Object val) {
        dataMap.put(key, val);
        dataExpireMap.put(key, DateUtil.addMinutes(new Date(), CACHE_HOLD_TIME_24H));
    }


    /**
     * 将一个key、value值放入内存缓存,并设置过期分钟数
     *
     * @param key
     * @param val
     * @param expireMiute
     */
    public static void put(String key, Object val, int expireMiute) {
        dataMap.put(key, val);
        dataExpireMap.put(key, DateUtil.addMinutes(new Date(), expireMiute));
    }

    /**
     * 从缓存中获取一个key的数据(若过期返回null)
     *
     * @param key
     * @return
     */
    public static   <T> T get(String cacheKey) {
        T obj = null;
        Date expireDate = CacheMapUtil.dataExpireMap.get(cacheKey);
        if (expireDate != null && expireDate.compareTo(new Date()) > 0) {
            obj =(T) (CacheMapUtil.dataMap.get(cacheKey));
        } else {
            System.out.printf("过期");
            // 过期时间已过自动删除
            clear(cacheKey);
        }
        return obj;
    }

    /**
     * 删除所有缓存
     */
    public static void clearAll() {
        dataMap.clear();
        dataExpireMap.clear();
    }

    /**
     * 删除某个缓存
     * @param key
     */
    public static void clear(String key) {
        logger.warn("删除 key:{}",key);
        dataMap.remove(key);
        dataExpireMap.remove(key);
    }

    /**
     * 返回所有缓存的时间
     * @return
     */
    public static  Map<String, Date> expireList() {
        return  dataExpireMap;

    }

    /**
     * 查询缓存是否包含key
     *
     * @param key
     * @return
     */
    public static boolean exists(String key) {
        return dataMap.containsKey(key);
    }
}

总结

注:不依赖第三方
Spring Boot 是一个开源的Java框架,它能够帮助开发者快速构建基于Spring的应用程序。为了提高应用程序的性能,Spring Boot提供了本地缓存的支持。本文将介绍如何使用ConcurrentLinkedHashMap实现Spring Boot本地缓存。 ConcurrentLinkedHashMap是一个线程安全的LRU缓存实现,它基于ConcurrentHashMap和LinkedHashMap。ConcurrentLinkedHashMap提供了以下特性: 1. 线程安全:ConcurrentLinkedHashMap是线程安全的,多个线程可以同时读写缓存。 2. LRU策略:ConcurrentLinkedHashMap使用LRU策略来管理缓存,当缓存满了之后,会将最近最少使用的缓存项删除。 3. 容量控制:ConcurrentLinkedHashMap提供了可配置的容量控制,开发者可以通过设置最大缓存大小来控制缓存的容量。 下面是使用ConcurrentLinkedHashMap实现Spring Boot本地缓存的步骤: 步骤1:添加依赖 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>com.googlecode.concurrentlinkedhashmap</groupId> <artifactId>concurrentlinkedhashmap-lru</artifactId> <version>1.4.2</version> </dependency> ``` 步骤2:创建缓存类 创建一个缓存类,它包含了ConcurrentLinkedHashMap实例和相关的方法。 ``` import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import org.springframework.stereotype.Component; import java.util.Map; @Component public class CacheService { private final Map<String, Object> cache; public CacheService() { cache = new ConcurrentLinkedHashMap.Builder<String, Object>() .maximumWeightedCapacity(1000) .build(); } public void put(String key, Object value) { cache.put(key, value); } public Object get(String key) { return cache.get(key); } public void remove(String key) { cache.remove(key); } public void clear() { cache.clear(); } } ``` 在上面的代码中,我们创建了一个CacheService类,它包含了ConcurrentLinkedHashMap实例和相关的方法。在构造函数中,我们使用ConcurrentLinkedHashMap.Builder创建了一个ConcurrentLinkedHashMap实例,并设置了最大容量为1000。 put、get、remove和clear方法分别用于向缓存中添加、获取、删除和清空数据。 步骤3:使用缓存类 在需要使用缓存的地方,我们可以通过依赖注入的方式获取CacheService实例,并使用其提供的方法进行缓存操作。 ``` import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @Autowired private CacheService cacheService; @GetMapping("/cache/{key}") public Object cache(@PathVariable String key) { Object value = cacheService.get(key); if (value == null) { // 查询数据库或其他操作 value = "data from db"; cacheService.put(key, value); } return value; } } ``` 在上面的代码中,我们注入了CacheService实例,并在cache方法中使用了它的get和put方法进行缓存操作。如果缓存中不存在指定的key,则查询数据库或其他操作,然后将结果存入缓存中。 这样,我们就使用ConcurrentLinkedHashMap实现了Spring Boot本地缓存。ConcurrentLinkedHashMap提供了线程安全、LRU策略和容量控制等特性,能够帮助我们提高应用程序的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值