Java 使用内存缓存数据、设置失效时间

 

场景: 项目上没redis, 使用内存缓存数据

TimeExpiredPoolCache.java
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

public class TimeExpiredPoolCache {

    private static  long defaultCachedMillis = 10 * 60 * 1000L;//过期时间默认10分钟
    private static long timerMillis = 10 * 60 * 1000L;//定时清理默认10分钟
    /**
     * 对象池
     */
    private static ConcurrentHashMap<String, DataWrapper<?>> dataPool = null;
    /**
     * 对象单例
     */
    private static TimeExpiredPoolCache instance = null;
    private TimeExpiredPoolCache() {
        dataPool = new ConcurrentHashMap<String, DataWrapper<?>>();
    }
    private static synchronized void syncInit() {
        if (instance == null) {
            instance = new TimeExpiredPoolCache();
            initTimer();
        }
    }
    public static TimeExpiredPoolCache getInstance() {
        if (instance == null) {
            syncInit();
        }
        return instance;
    }
    /**
     * 定时器定时清理过期缓存
     */
    private static Timer timer = new Timer();
    private static void initTimer() {
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    clearExpiredCaches();
                } catch (Exception e) {
                    //logger.error("clearExpiredCaches error.", e);
                }
            }
        }, timerMillis, timerMillis);
    }

    /**
     * 缓存数据
     * @param key key值
     * @param data 缓存数据
     * @param cachedMillis 过期时间
     * @param dataRenewer 刷新数据
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T put(String key, T data, long cachedMillis, DataRenewer<T> dataRenewer) throws Exception {
        DataWrapper<T> dataWrapper = (DataWrapper<T>)dataPool.get(key);
        if (data == null && dataRenewer != null) {
            data = dataRenewer.renewData();
        }
        //当重新获取数据为空,直接返回不做put
        if (data == null){
            return null;
        }
        if (dataWrapper != null) {
            //更新
            dataWrapper.update(data, cachedMillis);
        } else {
            dataWrapper = new DataWrapper<T>(data, cachedMillis);
            dataPool.put(key, dataWrapper);
        }
        return data;
    }
    /**
     * 直接设置缓存值和时间
     * @param key
     * @param data
     * @param cachedMillis
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T put(String key, T data, long cachedMillis) throws Exception{
        DataWrapper<T> dataWrapper = (DataWrapper<T>)dataPool.get(key);
        if (dataWrapper != null) {
            //更新
            dataWrapper.update(data, cachedMillis);
        } else {
            dataWrapper = new DataWrapper<T>(data, cachedMillis);
            dataPool.put(key, dataWrapper);
        }
        return data;
    }
    /**
     * 默认构造时间的缓存数据
     * @param key
     * @param data
     * @param dataRenewer
     * @return
     */
    @Deprecated
    public <T> T put(String key, T data, DataRenewer<T> dataRenewer) throws Exception {
        return put(key, data, defaultCachedMillis, dataRenewer);
    }
    /**
     * 获取缓存
     * @param key
     * @param cachedMillis
     * @param dataRenewer
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key, long cachedMillis, DataRenewer<T> dataRenewer) throws Exception {
        DataWrapper<T> dataWrapper = (DataWrapper<T>)dataPool.get(key);
        if (dataWrapper != null && !dataWrapper.isExpired()) {
            return dataWrapper.data;
        }
        return put(key, null, cachedMillis, dataRenewer);
    }
    @SuppressWarnings("unchecked")
    public <T> T get(String key) throws Exception {
        DataWrapper<T> dataWrapper = (DataWrapper<T>)dataPool.get(key);
        if (dataWrapper != null && !dataWrapper.isExpired()) {
            return dataWrapper.data;
        }
        return null;
    }
    /**
     * 清除缓存
     */
    public void clear() {
        dataPool.clear();
    }

    /**
     * 删除指定key的value
     * */
    public void remove(String key){
        dataPool.remove(key);
    }

    /**
     * 数据封装
     */
    private class DataWrapper<T> {
        /**
         * 数据
         */
        private T data;
        /**
         * 到期时间
         */
        private long expiredTime;
        /**
         * 缓存时间
         */
        private long cachedMillis;
        private DataWrapper(T data, long cachedMillis) {
            this.update(data, cachedMillis);
        }
        public void update(T data, long cachedMillis) {
            this.data = data;
            this.cachedMillis = cachedMillis;
            this.updateExpiredTime();
        }
        public void updateExpiredTime() {
            this.expiredTime = System.currentTimeMillis() + cachedMillis;
        }
        /**
         * 数据是否过期
         * @return
         */
        public boolean isExpired() {
            if (this.expiredTime > 0) {
                return System.currentTimeMillis() > this.expiredTime;
            }
            return true;
        }
    }
    /**
     * 数据构造
     */
    public interface DataRenewer<T> {
        public T renewData();
    }

    /**
     * 清除过期的缓存
     */
    private static void clearExpiredCaches() {
        List<String> expiredKeyList = new LinkedList<String>();

        for(Entry<String, DataWrapper<?>> entry : dataPool.entrySet()){
            if (entry.getValue().isExpired()) {
                expiredKeyList.add(entry.getKey());
            }
        }
        for (String key : expiredKeyList) {
            dataPool.remove(key);
        }
    }
}

CacheDemo.java
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CacheDemo {

    @RequestMapping(value = "/savePhone", method = RequestMethod.GET)
    public String  savePhone(){
        try {
            // 设置失效时间30秒
            TimeExpiredPoolCache.getInstance().put("phone","13800138000",30*1000L);
            new TimeThread().run();
            return "保存phone进入缓存成功";
        } catch (Exception e) {
            return "保存phone进入缓存失败";
        }
    }

    @RequestMapping(value = "/getPhone", method = RequestMethod.GET)
    public String  getPhone(){
        try {
            String  token = TimeExpiredPoolCache.getInstance().get("phone");
            if (null!=token){
                return token;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "数据为空................";
    }

    public static class TimeThread implements  Runnable{

        @Override
        public void run() {
            for(int i=30;i>0;i--){
                System.out.println("缓存倒计时:"+i+" 秒");
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

 

测试
1. 调getPhone接口

2. 调savePhone接口

  

3. 调getPhone接口

4. 失效时间30秒过后再次获取 getPhone

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 在Java使用Redis定期清理缓存数据,可以通过以下步骤实现: 1. 首先,需要在Java项目中引入Redis的Java客户端库,比如jedis。 2. 在项目中创建一个定时任务,可以使用Spring的@Scheduled注解来实现。 3. 在定时任务中,通过jedis客户端库连接Redis,然后使用Redis的命令来删除过期缓存数据。 4. 可以使用Redis的过期时间机制来自动清理过期缓存数据。在缓存数据存入Redis时,可以设置过期时间。 以下是Java代码示例: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; @Component public class CacheCleanupTask { @Autowired private Jedis jedis; @Scheduled(fixedRate = 60000) // 每60秒执行一次 public void cleanupCache() { // 使用Redis的命令来删除过期缓存数据 jedis.zremrangeByScore("myCache", 0, System.currentTimeMillis()); } } ``` 在上述代码中,使用了Spring的@Scheduled注解来表示该方法是一个定时任务。该方法会每60秒执行一次,使用jedis客户端库连接Redis,然后使用Redis的zremrangeByScore命令来删除过期缓存数据。这里使用了Redis的有序集合来存储缓存数据,其中缓存数据过期时间作为分值,可以使用zremrangeByScore命令来删除过期缓存数据。 ### 回答2: 在Java中,可以使用Redis提供的过期策略来定期清理缓存数据。Redis通过使用过期时间(expiry time)来自动清理过期缓存数据。 首先,需要确保在Java应用程序中配置好Redis的依赖。可以通过Maven或其他构建工具将Redis的Java客户端添加到项目中。 接下来,通过Java代码使用Redis相关的API来设置缓存数据过期时间。可以使用Jedis或Lettuce等Java Redis客户端库来实现。例如,使用Jedis客户端可以通过以下方式设置缓存数据过期时间: ```java Jedis jedis = new Jedis("localhost", 6379); // 创建Jedis客户端连接 jedis.set("key", "value"); // 设置缓存数据 jedis.expire("key", 3600); // 设置缓存数据过期时间为3600秒,1小时 ``` 以上代码中,`expire`方法用于设置缓存数据过期时间。在这个例子里,缓存数据过期时间设置为3600秒,即1小时。当缓存数据过期时间到达时,Redis会自动清理该缓存数据,以释放内存空间。 为了定期清理过期缓存数据,可以使用Redis的`EXPIRE`命令结合Redis的过期策略进行操作。可以在代码中添加一个定时任务,每隔一段时间执行以下操作: ```java Jedis jedis = new Jedis("localhost", 6379); // 创建Jedis客户端连接 Set<String> keys = jedis.keys("*"); // 获取所有缓存数据的key for (String key : keys) { jedis.expire(key, 0); // 通过设置过期时间为0秒触发缓存数据的自动清理 } ``` 以上代码中,通过`keys("*")`方法获取到所有缓存数据的key,然后通过`expire`方法将每个缓存数据过期时间设置为0秒。这会立即触发Redis的过期策略,导致过期缓存数据被清理。 通过以上方式,可以使用Java与Redis配合定期清理缓存数据。你可以根据具体的业务场景和需求来设置合适的过期时间和定时任务执行频率。 ### 回答3: 在Java使用Redis定期清理缓存数据,可以通过以下步骤进行操作: 1. 首先,需要在Java应用程序中引入Redis的相关依赖包。可以使用Maven或Gradle等构建工具来管理依赖关系。 2. 在Java代码中,使用Jedis或Lettuce等Redis客户端库连接到Redis服务器。 3. 创建一个定时任务,使用Java的定时任务框架,如Quartz或Spring的任务调度器,来定期执行缓存清理操作。 4. 在定时任务中,使用Redis的KEYS命令或SCAN命令获取所有缓存键。可以通过设置特定的缓存键前缀来区分不同类型的缓存数据。 5. 遍历所有缓存键,并使用DEL命令删除过期缓存数据。可以使用TTL命令获取键的剩余生存时间,并根据需求来判断是否过期。 6. 可以根据需要,设置定时任务的执行频率,如每小时、每天或每周执行一次。 7. 定期清理缓存数据时间间隔可以根据业务需求和缓存数据的生命周期来设定。较长的时间间隔可以降低对Redis服务器的压力,但可能会导致缓存数据存留时间较长,而较短的时间间隔可能会增加对服务器的负载。 需要注意的是,由于Redis的单线程特性,定期清理大量缓存数据可能会影响Redis服务器的性能。因此,可以考虑使用分布式缓存或搭建Redis集群来提高性能和可靠性。同时,在进行定期清理操作时,应尽量减少对Redis服务器的访问频率,以免对其他正常业务操作造成影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yixian123.com

谢谢打赏,祝老板心想事成

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值