From 60fea362521fe206735306cadc56e65ece4644be Mon Sep 17 00:00:00 2001 From: clchen Date: Wed, 9 May 2018 20:24:17 +0800 Subject: [PATCH] reimplement lru cache in thread safe --- .../jayway/jsonpath/spi/cache/LRUCache.java | 120 ++++++------------ 1 file changed, 41 insertions(+), 79 deletions(-) diff --git a/json-path/src/main/java/com/jayway/jsonpath/spi/cache/LRUCache.java b/json-path/src/main/java/com/jayway/jsonpath/spi/cache/LRUCache.java index 3646e2c8..af496ec5 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/spi/cache/LRUCache.java +++ b/json-path/src/main/java/com/jayway/jsonpath/spi/cache/LRUCache.java @@ -12,101 +12,63 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.jayway.jsonpath.spi.cache; import com.jayway.jsonpath.JsonPath; -import java.util.Deque; -import java.util.LinkedList; +import java.util.LinkedHashMap; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; public class LRUCache implements Cache { - private final ReentrantLock lock = new ReentrantLock(); - - private final Map map = new ConcurrentHashMap(); - private final Deque queue = new LinkedList(); - private final int limit; - - public LRUCache(int limit) { - this.limit = limit; - } - - public void put(String key, JsonPath value) { - JsonPath oldValue = map.put(key, value); - if (oldValue != null) { - removeThenAddKey(key); - } else { - addKey(key); - } - if (map.size() > limit) { - map.remove(removeLast()); - } - } - - public JsonPath get(String key) { - JsonPath jsonPath = map.get(key); - if(jsonPath != null){ - removeThenAddKey(key); - } - return jsonPath; - } - - private void addKey(String key) { - lock.lock(); - try { - queue.addFirst(key); - } finally { - lock.unlock(); - } - } - - private String removeLast() { - lock.lock(); - try { - final String removedKey = queue.removeLast(); - return removedKey; - } finally { - lock.unlock(); - } - } - - private void removeThenAddKey(String key) { - lock.lock(); - try { - queue.removeFirstOccurrence(key); - queue.addFirst(key); - } finally { - lock.unlock(); - } - - } - - private void removeFirstOccurrence(String key) { - lock.lock(); - try { - queue.removeFirstOccurrence(key); - } finally { - lock.unlock(); - } + private static final float DEFAULT_LOAD_FACTOR = 0.75f; + private final ReentrantLock lock = new ReentrantLock(); + private int size; + private LinkedHashMap hashMap; + + public LRUCache(int size) { + this.size = size; + int capacity = (int) Math.ceil(size / DEFAULT_LOAD_FACTOR) + 1; + hashMap = new LinkedHashMap(capacity, DEFAULT_LOAD_FACTOR, true) { + // (an anonymous inner class) + private static final long serialVersionUID = 1; + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > LRUCache.this.size; + } + }; + } + + public void put(String key, JsonPath value) { + synchronized (this) { + hashMap.put(key, value); } + } - public JsonPath getSilent(String key) { - return map.get(key); + public JsonPath get(String key) { + synchronized (this) { + return hashMap.get(key); } + } - public void remove(String key) { - removeFirstOccurrence(key); - map.remove(key); + public JsonPath getSilent(String key) { + synchronized (this) { + return hashMap.get(key); } + } - public int size() { - return map.size(); + public int size() { + synchronized (this) { + return hashMap.size(); } + } - public String toString() { - return map.toString(); + public String toString() { + synchronized (this) { + return hashMap.toString(); } + } } \ No newline at end of file