编程语言
首页 > 编程语言> > Java缓存超时

Java缓存超时

作者:互联网

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

我想要这样的代码:

 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中实现一个短计时器.到期后,将以同步方式检查实际计时器.但是,这是很多代码,所以一个更简单的主意会很好.

解决方法:

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

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;
    }
  }
}

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

请注意,尽管此实现避免了锁定,但由于竞赛事件,它仍然易于重复刷新.如果可以满足您的要求,那应该没问题.但是,如果您有更严格的要求,则需要放置锁定以正确同步线程并避免争用事件.

标签:caching,nonblocking,java
来源: https://codeday.me/bug/20191127/2075771.html