diff --git a/redisson/src/main/java/org/redisson/cache/LRUCacheMap.java b/redisson/src/main/java/org/redisson/cache/LRUCacheMap.java index d90ebf471..b30d09a0e 100644 --- a/redisson/src/main/java/org/redisson/cache/LRUCacheMap.java +++ b/redisson/src/main/java/org/redisson/cache/LRUCacheMap.java @@ -15,8 +15,14 @@ */ package org.redisson.cache; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; /** * LRU (least recently used) cache. @@ -28,24 +34,38 @@ import java.util.concurrent.ConcurrentLinkedQueue; */ public class LRUCacheMap extends AbstractCacheMap { - private final Queue queue = new ConcurrentLinkedQueue(); + private final AtomicLong index = new AtomicLong(); + private final List>> queues = + new ArrayList>>(Runtime.getRuntime().availableProcessors()*2); public LRUCacheMap(int size, long timeToLiveInMillis, long maxIdleInMillis) { super(size, timeToLiveInMillis, maxIdleInMillis); + + for (int i = 0; i < Runtime.getRuntime().availableProcessors()*2; i++) { + Set> instance = Collections.synchronizedSet(new LinkedHashSet>()); + queues.add(instance); + } } @Override - protected void onValueCreate(CachedValue value) { + protected void onValueCreate(CachedValue value) { + Collection> queue = getQueue(value); queue.add(value); } + + private Collection> getQueue(CachedValue value) { + return queues.get(value.hashCode() % queues.size()); + } @Override - protected void onValueRemove(CachedValue value) { + protected void onValueRemove(CachedValue value) { + Collection> queue = getQueue(value); queue.remove(value); } @Override - protected void onValueRead(CachedValue value) { + protected void onValueRead(CachedValue value) { + Collection> queue = getQueue(value); // move value to tail of queue if (queue.remove(value)) { queue.add(value); @@ -54,15 +74,22 @@ public class LRUCacheMap extends AbstractCacheMap { @Override protected void onMapFull() { - CachedValue value = queue.poll(); - if (value != null) { - map.remove(value.getKey(), value); + Collection> queue = queues.get((int)Math.abs(index.incrementAndGet() % queues.size())); + synchronized (queue) { + Iterator> iter = queue.iterator(); + if (iter.hasNext()) { + CachedValue value = iter.next(); + iter.remove(); + map.remove(value.getKey(), value); + } } } @Override public void clear() { - queue.clear(); + for (Collection> collection : queues) { + collection.clear(); + } super.clear(); }