Java中怎么设置缓存Map过期时间
创始人
2024-12-24 17:01:53
0次

1. ExpiringMap

功能简介 :

1.可设置Map中的Entry在一段时间后自动过期。

2.可设置Map最大容纳值,当到达Maximum size后,再次插入值会导致Map中的第一个值过期。

3.可添加监听事件,在监听到Entry过期时调度监听函数。

4.可以设置懒加载,在调用get()方法时创建对象。

github地址:https://github.com/jhalterman/expiringmap/

maven添加依赖即可使用

  net.jodah   expiringmap   0.5.8

public static void main(String[] args) throws InterruptedException {    ExpiringMap map = ExpiringMap.builder()        .maxSize(100)        .expiration(1, TimeUnit.SECONDS)        .expirationPolicy(ExpirationPolicy.ACCESSED)        .variableExpiration()        .build();    map.put("test","test123");    Thread.sleep(500);    String test= map.get("test");    System.err.println(test); }

2.Guava - LoadingCache

Google开源出来的一个线程安全的本地缓存解决方案。

特点:提供缓存回收机制,监控缓存加载/命中情况,灵活强大的功能,简单易上手的api

但是该cache不会在特定时间准时回收键值,所以不适用于我当前的业务场景。

 com.google.guava  guava  27.1-jre

3. ExpiryMap

这是网上某位大佬自己封装的map,继承至HashMap,重写了所有对外的方法,对每个key值都设置了有效期。

我在其基础上增加了使用单例模式获取map。

import java.util.*;/** * @Title: ExpiryMap 可以设置过期时间的Map * @description ExpiryMap继承至HashMap 重写了所有对外的方法,对每个key值都设置了有效期 * @Author: xx * @Version: 1.0 */public class ExpiryMap extends HashMap {  private static final long serialVersionUID = 1L;  /**   * default expiry time 2s   */  private long EXPIRY = 1000 * 2;  private HashMap expiryMap = new HashMap<>();  /** 缓存实例对象 */  private volatile static ExpiryMap SameUrlMap;  /**   * 采用单例模式获取实例   * @return   */  public static ExpiryMap getInstance() {    //第一次判空,提高效率    if (null == SameUrlMap) {      //保证线程安全      synchronized (ExpiryMap.class) {        //第二次判空,保证单例对象的唯一性,防止第一次有多个线程进入第一个if判断        if (null == SameUrlMap) {          SameUrlMap = new ExpiryMap<>();        }      }    }    return SameUrlMap;  }  public ExpiryMap(){    super();  }  public ExpiryMap(long defaultExpiryTime){    this(1 << 4, defaultExpiryTime);  }  public ExpiryMap(int initialCapacity, long defaultExpiryTime){    super(initialCapacity);    this.EXPIRY = defaultExpiryTime;  }  @Override  public V put(K key, V value) {    expiryMap.put(key, System.currentTimeMillis() + EXPIRY);    return super.put(key, value);  }  @Override  public boolean containsKey(Object key) {    return !checkExpiry(key, true) && super.containsKey(key);  }  /**   * @param key   * @param value   * @param expiryTime 键值对有效期 毫秒   * @return   */  public V put(K key, V value, long expiryTime) {    expiryMap.put(key, System.currentTimeMillis() + expiryTime);    return super.put(key, value);  }  @Override  public int size() {    return entrySet().size();  }  @Override  public boolean isEmpty() {    return entrySet().size() == 0;  }  @Override  public boolean containsValue(Object value) {    if (value == null) {      return Boolean.FALSE;    }    Set> set = super.entrySet();    Iterator> iterator = set.iterator();    while (iterator.hasNext()) {      java.util.Map.Entry entry = iterator.next();      if(value.equals(entry.getValue())){        if(checkExpiry(entry.getKey(), false)) {          iterator.remove();          return Boolean.FALSE;        }else {          return Boolean.TRUE;        }      }    }    return Boolean.FALSE;  }  @Override  public Collection values() {    Collection values = super.values();    if(values == null || values.size() < 1) {      return values;    }    Iterator iterator = values.iterator();    while (iterator.hasNext()) {      V next = iterator.next();      if(!containsValue(next)) {        iterator.remove();      }    }    return values;  }  @Override  public V get(Object key) {    if (key == null) {      return null;    }    if(checkExpiry(key, true)) {      return null;    }    return super.get(key);  }  /**   *   * @Description: 是否过期   * @param key   * @return null:不存在或key为null -1:过期 存在且没过期返回value 因为过期的不是实时删除,所以稍微有点作用   */  public Object isInvalid(Object key) {    if (key == null) {      return null;    }    if(!expiryMap.containsKey(key)){      return null;    }    long expiryTime = expiryMap.get(key);    boolean flag = System.currentTimeMillis() > expiryTime;    if(flag){      super.remove(key);      expiryMap.remove(key);      return -1;    }    return super.get(key);  }  @Override  public void putAll(Map m) {    for (Map.Entry e : m.entrySet()) {      expiryMap.put(e.getKey(), System.currentTimeMillis() + EXPIRY);    }    super.putAll(m);  }  @Override  public Set> entrySet() {    Set> set = super.entrySet();    Iterator> iterator = set.iterator();    while (iterator.hasNext()) {      java.util.Map.Entry entry = iterator.next();      if(checkExpiry(entry.getKey(), false)) {        iterator.remove();      }    }    return set;  }  /**   *   * @Description: 是否过期   * @param expiryTime true 过期   * @param isRemoveSuper true super删除   * @return   */  private boolean checkExpiry(Object key, boolean isRemoveSuper){    if(!expiryMap.containsKey(key)){      return Boolean.FALSE;    }    long expiryTime = expiryMap.get(key);    boolean flag = System.currentTimeMillis() > expiryTime;    if(flag){      if(isRemoveSuper) {        super.remove(key);      }      expiryMap.remove(key);    }    return flag;  }  public static void main(String[] args) throws InterruptedException {    ExpiryMap map = new ExpiryMap<>();    map.put("test", "xxx");    map.put("test2", "ankang", 5000);    System.out.println("test==" + map.get("test"));    Thread.sleep(3000);    System.out.println("test==" + map.get("test"));    System.out.println("test2==" + map.get("test2"));    Thread.sleep(3000);    System.out.println("test2==" + map.get("test2"));  }}

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...