当前位置: 首页 > 知识库问答 >
问题:

基于Java时间的映射/缓存,密钥过期[已关闭]

夏侯昆琦
2023-03-14

原始关闭原因未解决

你们知道Java Map或类似的标准数据存储在给定的超时后自动清除条目吗?这意味着老化,旧的过期条目会自动“老化”。

最好是在可以通过Maven访问的开源库中?

我知道自己实现功能的方法,并且在过去已经做了几次,所以我不是在征求这方面的建议,而是寻求一个好的参考实现的指针。

基于WeakReference的解决方案(如WeakHashMap)不是一个选项,因为我的密钥可能是非内部字符串,我想要一个不依赖垃圾收集器的可配置超时。

Ehcache也是一个我不想依赖的选项,因为它需要外部配置文件。我正在寻找一个代码唯一的解决方案。

共有3个答案

钮承恩
2023-03-14

Apache Commons为地图过期条目提供了decorator:被动式ExpiringMap它比Guava的缓存更简单。

注意,它不同步

郗浩
2023-03-14

这是我为相同需求所做的示例实现,并发运行良好。可能对某人有用。

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 
 * @author Vivekananthan M
 *
 * @param <K>
 * @param <V>
 */
public class WeakConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {

    private static final long serialVersionUID = 1L;

    private Map<K, Long> timeMap = new ConcurrentHashMap<K, Long>();
    private long expiryInMillis = 1000;
    private static final SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss:SSS");

    public WeakConcurrentHashMap() {
        initialize();
    }

    public WeakConcurrentHashMap(long expiryInMillis) {
        this.expiryInMillis = expiryInMillis;
        initialize();
    }

    void initialize() {
        new CleanerThread().start();
    }

    @Override
    public V put(K key, V value) {
        Date date = new Date();
        timeMap.put(key, date.getTime());
        System.out.println("Inserting : " + sdf.format(date) + " : " + key + " : " + value);
        V returnVal = super.put(key, value);
        return returnVal;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        for (K key : m.keySet()) {
            put(key, m.get(key));
        }
    }

    @Override
    public V putIfAbsent(K key, V value) {
        if (!containsKey(key))
            return put(key, value);
        else
            return get(key);
    }

    class CleanerThread extends Thread {
        @Override
        public void run() {
            System.out.println("Initiating Cleaner Thread..");
            while (true) {
                cleanMap();
                try {
                    Thread.sleep(expiryInMillis / 2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void cleanMap() {
            long currentTime = new Date().getTime();
            for (K key : timeMap.keySet()) {
                if (currentTime > (timeMap.get(key) + expiryInMillis)) {
                    V value = remove(key);
                    timeMap.remove(key);
                    System.out.println("Removing : " + sdf.format(new Date()) + " : " + key + " : " + value);
                }
            }
        }
    }
}


Git Repo链接(带监听器实现)

https://github.com/vivekjustthink/WeakConcurrentHashMap

干杯

翟俊名
2023-03-14

对谷歌收藏(Google Collections,简称Guava)现在有一种叫做MapMaker的东西,可以做到这一点。

ConcurrentMap<Key, Graph> graphs = new MapMaker()
   .concurrencyLevel(4)
   .softKeys()
   .weakValues()
   .maximumSize(10000)
   .expiration(10, TimeUnit.MINUTES)
   .makeComputingMap(
       new Function<Key, Graph>() {
         public Graph apply(Key key) {
           return createExpensiveGraph(key);
         }
       });

更新:

自guava 10.0(2011年9月28日发布)起,许多地图制作方法已被弃用,取而代之的是新的CacheBuilder:

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
    .maximumSize(10000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build(
        new CacheLoader<Key, Graph>() {
          public Graph load(Key key) throws AnyException {
            return createExpensiveGraph(key);
          }
        });
 类似资料:
  • 问题内容: 你是否知道在给定超时后会自动清除条目的Java Map或类似标准数据存储?这意味着老化,旧的过期条目会自动“老化”。 最好在可通过Maven访问的开源库中? 我知道自己实现该功能的方法,并且过去已经做过几次,所以我并不是在这方面寻求建议,而是寻求指向一个好的参考实现的指针。 像WeakHashMap这样的基于WeakReference的解决方案不是一个选择,因为我的密钥很可能是非int

  • 问题内容: 我的代码如下所示: 它的作用是,将键值存储23小时。但是,有什么方法可以设置密钥在晚上11:59 pm过期? 问题答案: Redis本身不提供此功能。但是您可以计算直到午夜的秒数。

  • 我有一个Spring应用程序,它使用MyBatis进行持久化。我使用ehcache是因为速度对于这个应用程序很重要。我已经设置并配置了MyBatis和Ehcache。我使用一个名为“mybatis”的单一缓存,因为否则为每个实体创建单独的缓存将是荒谬的。 这是我的电子缓存。xml。 这是我的mybatis映射器界面的一个示例。 因为我有一个共享缓存,所以我需要一种方法使我的密钥对域对象是唯一的。作

  • 这是我的密码 抱歉,如果我的代码一团糟。

  • 本文向大家介绍Java缓存Map设置过期时间实现解析,包括了Java缓存Map设置过期时间实现解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Java缓存Map设置过期时间实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 最近项目需求需要一个类似于redis可以设置过期时间的K,V存储方式。项目前期暂时不引进redis

  • 前缀映射,后缀映射和缓存映射 通过 names.NewPrefixMapper(names.SnakeMapper{}, "prefix") 可以创建一个在 SnakeMapper 的基础上在命名中添加统一的前缀,当然也可以把 SnakeMapper{} 换成 SameMapper 或者你自定义的 Mapper。 例如,如果希望所有的表名都在结构体自动命名的基础上加一个前缀而字段名不加前缀,则可以