I am populating my guava cache from multiple threads by calling add
method. Now from the background thread which runs every 30 seconds, I want to send whatever is t
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.