-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Closed
Description
hey,
thanks for the great library.
I'm using it for a long time, but recently I came up with something strange regarding expireAfterWrite eviction.
I don't get exactly get the semantics of the Map view (asMap), since it can or can not be up to date like the API docs tells.
But still, I've got this issue in production that puzzles me:
public static void main(String[] args) {
Object PRESENT = new Object();
Cache<String,Object> cache = Caffeine.newBuilder()
.expireAfterWrite(Duration.ofSeconds(3))
.build();
Consumer<Long> sleepQuietly = millis -> {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
}
};
new Thread(() -> {
String name = "u1";
for (int i = 0; i < 10; i++) {
cache.put(name, PRESENT);
// System.out.println(name + ": crowd = " + List.copyOf(cache.asMap().keySet())); // ERR
System.out.println(name + ": crowd = " + cache.asMap().keySet().stream().collect(toList())); // OK
sleepQuietly.accept(500L);
}
}).start();
new Thread(() -> {
String name = "u2";
sleepQuietly.accept(1000L);
cache.put(name, PRESENT);
// System.out.println(name + ": crowd = " + List.copyOf(cache.asMap().keySet())); // ERR
System.out.println(name + ": crowd = " + cache.asMap().keySet().stream().collect(toList())); // OK
}).start();
}
Simply put:
- eviction is after write 3s
- u1 thread put every 500ms
- u2 thread put after 1s
If I use List.copyOf that relies on toArray() on the key set view, u1 never sees u2 being evicted:
u1: crowd = [u1]
u1: crowd = [u1]
u2: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
If the set is traversed using a stream, or the iterator in anyway, I've got the proper eviction:
u1: crowd = [u1]
u1: crowd = [u1]
u2: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1, u2]
u1: crowd = [u1]
u1: crowd = [u1]
Is this normal that keySet iteration works but not the toArray method? If I use List.copyOf or new ArrayList this does not work.
I certainly was not expected this :)
thanks a lot,
Metadata
Metadata
Assignees
Labels
No labels