问题
Current eviction algorithm for maps is quite lazy. It looks like expired objects are evicted only when the data structure is accessed.
For example, the map from addresses to indexers defined as:
ConcurrentMap<Address, Indexer> indexers = new MapMaker()
.expireAfterAccess( EXPIRATION, TimeUnit.SECONDS)
.evictionListener( new IndexEvicted())
.makeMap();
leads to quite surprising pattern: while containsKey()
for the given address returns false, immediately after that indexer for that address is evicted.
What would be the recommended approach to make the clean up process more real-time? I.e. to remove the objects close to the actual expiration time.
Update: I'd like to more clarify what I mean by real-time. For the example above, EXPIRATION being 10 seconds, I'd like to see the inserted object evicted in 10 seconds after last access. That is not happening now - the map must be used somehow to start the eviction. If the map is completely unused, the object can stay there for years.
回答1:
In order to have timely eviction, Guava would need to implement some sort of background thread or a timed recurring task. Doing so would make the map more heavy weight and harder to use in environments like J2EE or environments where the security policy prevents threads from being spawned willy-nilly.
If you care about timely eviction, set up your own timed thread that touches the map.
On the flip side, I do agree that having a garbage-collector triggered eviction would be nice... for example by using a SoftReference and a finalizer. (Yes, I know finalizers are mostly evil, I am simply suggesting an optional last-resort strategy.)
回答2:
There is an expireAfterWrite
method in addition to expireAfterAccess
. That probably fits the bill.
From javadoc:
Specifies that each entry should be automatically removed from the map once a fixed duration has passed since the entry's creation or replacement. Note that changing the value of an entry will reset its expiration time.
Note: both expireAfterAccess
and expireAfterWrite
are "real-time", it's just that one expires elements based on their last write time, the other is based on their last access time.
回答3:
While Dilum's answer makes the most sense, also note that touching a data structure with automatic eviction will not necessarily evict all expired entries. Most expiry happens in relatively small batches and therefore, if you have a large number of simultaneous expirations, you might have to touch the data structure a number of times. Unfortunately, I don't think there there is an easy programmatic way to do this reliably.
来源:https://stackoverflow.com/questions/5899383/laziness-of-eviction-in-guavas-maps