首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java缓存的超时

java缓存的超时
EN

Stack Overflow用户
提问于 2012-09-14 11:21:53
回答 1查看 3.1K关注 0票数 3

我们有一个简单但非常常用的缓存,由ConcurrentHashMap实现。现在,我们希望定期刷新所有值(例如,每15分钟一次)。

我想要这样的代码:

代码语言:javascript
复制
 private void regularCacheCleanup() {
        final long now = System.currentTimeMillis();
        final long delta = now - cacheCleanupLastTime;
        if (delta < 0 || delta > 15 * 60 * 1000) {
            cacheCleanupLastTime = now;
            clearCache();
        }
  }

但应包括:

  • 螺纹安全
  • 如果缓存不被清除,则非阻塞且性能极佳。
  • 除了java.*类(所以没有Google CacheBuilder)之外,没有任何依赖项。
  • 石固;-)
  • 无法启动新线程

现在,我想在ThreadLocal中实现一个短计时器。当它过期时,将以同步的方式检查真正的计时器。然而,这是一个非常多的代码,所以一个更简单的想法会更好。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-09-14 12:10:38

解决这个问题的主流方法是使用一些计时器线程在指定的时间间隔内刷新缓存。但是,由于您不需要创建新线程,我可以想到的一个可能的实现是伪时间缓存刷新。基本上,我会在缓存访问器(put和get方法)中插入检查,每次客户端使用这些方法时,我都会在执行put或get操作之前检查缓存是否需要刷新。这是一个粗略的想法:

代码语言:javascript
复制
class YourCache {

  // holds the last time the cache has been refreshed in millis
  private volatile long lastRefreshDate;

  // indicates that cache is currently refreshing entries
  private volatile boolean cacheCurrentlyRefreshing;

  private Map cache = // Your concurrent map cache...

  public void put(Object key, Object element) {
    if (cacheNeedsRefresh()) {
      refresh();
    }
    map.put(key, element);
  }

  public Object get(Object key) {
    if (cacheNeedsRefresh()) {
      refresh();
    }
    return map.get(key);
  }

  private boolean cacheNeedsRefresh() {
    // make sure that cache is not currently being refreshed by some
    // other thread.
    if (cacheCurrentlyRefreshing) {
      return false;
    }
    return (now - lastRefreshDate) >= REFRESH_INTERVAL;
  } 

  private void refresh() {
    // make sure the cache did not start refreshing between cacheNeedsRefresh()
    // and refresh() by some other thread.
    if (cacheCurrentlyRefreshing) {
      return;
    }

    // signal to other threads that cache is currently being refreshed.
    cacheCurrentlyRefreshing = true;

    try {
      // refresh your cache contents here
    } finally {
       // set the lastRefreshDate and signal that cache has finished
       // refreshing to other threads.
       lastRefreshDate = System.currentTimeMillis();
       cahceCurrentlyRefreshing = false;
    }
  }
}

就我个人而言,我不会考虑这样做,但是如果您不想或者不能创建计时器线程,那么这可能是您的一个选择。

请注意,虽然此实现避免了锁,但由于竞赛事件,它仍然容易出现重复刷新。如果这对您的需求是可以的,那么它应该没有问题。但是,如果您有更严格的要求,那么您需要设置锁定,以便正确地同步线程并避免竞争事件。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12423502

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档