How to empty Guava cache every 30 seconds while sending it to another method?

独自空忆成欢 提交于 2019-12-02 01:16:11

How about:

@Override
public void run() {
  ImmutableMap<Integer, List<Process>> snapshot = ImmutableMap.copyOf(cache.asMap());
  cache.invalidateAll();
  sendToDB(snapshot);
}

This will copy the contents of the cache into a new map, creating a snapshot of the cache at a particular point in time. Then .invalidateAll() will empty the cache, after which the snapshot will be sent to the DB.

One disadvantage with this approach is it's racy - it's possible for entries to be added to the cache after the snapshot is created but before .invalidateAll() is called, and such entries would never be sent to the DB. Since your cache could also evict entries due to the maximumSize() setting I assume this isn't a concern, but if it is you'd want to instead remove the entry while constructing the snapshot, which would look like this:

@Override
public void run() {
  Iterator<Entry<Integer, List<Process>> iter = cache.asMap().entrySet().iterator();
  ImmutableMap<Integer, List<Process>> builder = ImmutableMap.builder();
  while (iter.hasNext()) {
    builder.add(iter.next());
    iter.remove();
  }
  sendToDB(builder.build());
}

With this approach the cache may not actually be empty when sendToDB() is invoked, but every entry that was there before the snapshotting began will have been removed and will be sent to the database.

Alternatively you could create a wrapper class that has a Cache field, and atomically swap the field out for a new empty cache, then copy the contents of the old cache to the database and allow it to be GCed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!